From c5420fea167f22f6a79205d586f8efaab33858d5 Mon Sep 17 00:00:00 2001 From: Masum Reza <50095635+JohnRTitor@users.noreply.github.com> Date: Wed, 18 Oct 2023 11:06:36 +0530 Subject: [PATCH 1/4] Added File organizer --- projects/File_Organizer/main.py | 54 +++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 projects/File_Organizer/main.py diff --git a/projects/File_Organizer/main.py b/projects/File_Organizer/main.py new file mode 100644 index 00000000..89a6bc76 --- /dev/null +++ b/projects/File_Organizer/main.py @@ -0,0 +1,54 @@ +import sys +import os +import shutil # For moving files + +def main(): + try: + check_arguments() + organize_directory(sys.argv[1]) + except ValueError as e: + print(e) + sys.exit(1) + +def check_arguments(): + # One argument needs to be provided, that is the path of the directory to be organized + if len(sys.argv) - 1 != 1: + raise ValueError(f"Usage: python3 {sys.argv[0]} ") + directory_path = sys.argv[1] + + if not os.path.isdir(directory_path): + raise ValueError(f"'{directory_path}' is not a valid directory.") + + if not os.listdir(directory_path): + raise ValueError(f"'{directory_path}' is an empty directory!") + +def organize_directory(directory_path): + categories = { + "Music": (".mp3", ".wav", ".flac", ".m4a", ".aac", ".ogg", ".oga" ".wma", ".mid"), + "Videos": (".mp4", ".avi", ".mkv", ".mpeg", ".wmv", ".vob", ".flv", ".mov", ".3gp", ".webm"), + "Source Files": (".py", ".c", ".cpp", ".java", ".js", ".cs", ".html", ".css", ".php", ".json", ".xml", ".sql", ".db"), + "Executables": (".exe", ".msi", ".sh", ".bat", ".apk", ".jar", ".deb", ".run", ".bin", ".dmg", ".iso"), + "Pictures": (".jpg", ".jpeg", ".png", ".gif", ".bmp", ".svg", ".webp", ".psd", ".ai", ".ico"), + "Documents": (".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".txt", ".md", ".odt", ".ods", ".odp", ".csv", ".rtf"), + "Compressed": (".zip", ".rar", ".tar", ".gz", ".7z", ".bz2", ".xz", ".z", ".lz"), + "Torrents": (".torrent",), + } + + for category, extensions in categories.items(): + # Create folders for each category, if they don't already exist + category_folder = os.path.join(directory_path, category) + os.makedirs(category_folder, exist_ok=True) + + for file in os.listdir(directory_path): + # Process only files, not directories + if os.path.isfile(os.path.join(directory_path, file)): + # extract the file extension of the current file + file_extension = os.path.splitext(file)[1] + if file_extension.lower() in extensions: + source_path = os.path.join(directory_path, file) + dest_path = os.path.join(category_folder, file) + shutil.move(source_path, dest_path) + print(f"Moved '{file}' to '{category}' folder.") + +if __name__ == "__main__": + main() \ No newline at end of file From 29a0cfaa4b5bb817cd1534cc7db6cd124d227eb2 Mon Sep 17 00:00:00 2001 From: Masum Reza <50095635+JohnRTitor@users.noreply.github.com> Date: Fri, 27 Oct 2023 14:14:43 +0530 Subject: [PATCH 2/4] Used argparse instead of sys --- projects/File_Organizer/main.py | 62 ++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/projects/File_Organizer/main.py b/projects/File_Organizer/main.py index 89a6bc76..c84abf7c 100644 --- a/projects/File_Organizer/main.py +++ b/projects/File_Organizer/main.py @@ -1,28 +1,32 @@ -import sys +import argparse import os import shutil # For moving files def main(): try: - check_arguments() - organize_directory(sys.argv[1]) + args = parse_arguments() + check_directory(args.directory_path) + organize_directory(args.directory_path, args.verbose) except ValueError as e: print(e) - sys.exit(1) - -def check_arguments(): - # One argument needs to be provided, that is the path of the directory to be organized - if len(sys.argv) - 1 != 1: - raise ValueError(f"Usage: python3 {sys.argv[0]} ") - directory_path = sys.argv[1] - + +def parse_arguments(): + parser = argparse.ArgumentParser(description="Organize files in a directory based on their extensions.") + parser.add_argument("directory_path", type=str, help="Path of the directory to be organized") + parser.add_argument("-v", "--verbose", action="store_true", help="Enable verbose output") + return parser.parse_args() + +def check_directory(directory_path): if not os.path.isdir(directory_path): raise ValueError(f"'{directory_path}' is not a valid directory.") if not os.listdir(directory_path): raise ValueError(f"'{directory_path}' is an empty directory!") + + if not os.access(directory_path, os.W_OK): + raise ValueError(f"'{directory_path}' is not writable.") -def organize_directory(directory_path): +def organize_directory(directory_path, verbose=False): categories = { "Music": (".mp3", ".wav", ".flac", ".m4a", ".aac", ".ogg", ".oga" ".wma", ".mid"), "Videos": (".mp4", ".avi", ".mkv", ".mpeg", ".wmv", ".vob", ".flv", ".mov", ".3gp", ".webm"), @@ -35,20 +39,28 @@ def organize_directory(directory_path): } for category, extensions in categories.items(): - # Create folders for each category, if they don't already exist - category_folder = os.path.join(directory_path, category) - os.makedirs(category_folder, exist_ok=True) - - for file in os.listdir(directory_path): - # Process only files, not directories - if os.path.isfile(os.path.join(directory_path, file)): - # extract the file extension of the current file - file_extension = os.path.splitext(file)[1] - if file_extension.lower() in extensions: - source_path = os.path.join(directory_path, file) - dest_path = os.path.join(category_folder, file) - shutil.move(source_path, dest_path) + # Check if there are files with matching extensions for this category + files_with_extension = [file for file in os.listdir(directory_path) if os.path.isfile(os.path.join(directory_path, file)) + and os.path.splitext(file)[1].lower() in extensions] + + if files_with_extension: + # Create a folder for this category if it doesn't exist + category_folder = os.path.join(directory_path, category) + if not os.path.exists(category_folder): + os.makedirs(category_folder) + if verbose: + print(f"Creating '{category}' folder.") + elif verbose: + print(f"'{category}' folder already exists, reusing.") + + for file in files_with_extension: + source_path = os.path.join(directory_path, file) + dest_path = os.path.join(category_folder, file) + shutil.move(source_path, dest_path) + if verbose: print(f"Moved '{file}' to '{category}' folder.") + print("Organizing files complete!") + if __name__ == "__main__": main() \ No newline at end of file From 0e8a3497a74317d7872e848cfba8490683ce8ce5 Mon Sep 17 00:00:00 2001 From: Masum Reza <50095635+JohnRTitor@users.noreply.github.com> Date: Fri, 27 Oct 2023 14:29:56 +0530 Subject: [PATCH 3/4] Use logging module --- projects/File_Organizer/main.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/projects/File_Organizer/main.py b/projects/File_Organizer/main.py index c84abf7c..da41d050 100644 --- a/projects/File_Organizer/main.py +++ b/projects/File_Organizer/main.py @@ -1,12 +1,19 @@ import argparse import os +import logging import shutil # For moving files def main(): try: args = parse_arguments() check_directory(args.directory_path) - organize_directory(args.directory_path, args.verbose) + + # log if verbose is enabled + log_format = "%(message)s" # This will only log the message content, without any prefix + logging.basicConfig(level=logging.INFO if args.verbose else logging.WARNING, format=log_format) + + organize_directory(args.directory_path) + # Catch any exceptions that may occur except ValueError as e: print(e) @@ -26,7 +33,7 @@ def check_directory(directory_path): if not os.access(directory_path, os.W_OK): raise ValueError(f"'{directory_path}' is not writable.") -def organize_directory(directory_path, verbose=False): +def organize_directory(directory_path): categories = { "Music": (".mp3", ".wav", ".flac", ".m4a", ".aac", ".ogg", ".oga" ".wma", ".mid"), "Videos": (".mp4", ".avi", ".mkv", ".mpeg", ".wmv", ".vob", ".flv", ".mov", ".3gp", ".webm"), @@ -48,17 +55,15 @@ def organize_directory(directory_path, verbose=False): category_folder = os.path.join(directory_path, category) if not os.path.exists(category_folder): os.makedirs(category_folder) - if verbose: - print(f"Creating '{category}' folder.") - elif verbose: - print(f"'{category}' folder already exists, reusing.") + logging.info(f"Creating '{category}' folder.") + else: + logging.info(f"'{category}' folder already exists, reusing.") for file in files_with_extension: source_path = os.path.join(directory_path, file) dest_path = os.path.join(category_folder, file) shutil.move(source_path, dest_path) - if verbose: - print(f"Moved '{file}' to '{category}' folder.") + logging.info(f"Moved '{file}' to '{category}' folder.") print("Organizing files complete!") From 1b6fb251f3f42ba7d31d7e013ae5da2db7370358 Mon Sep 17 00:00:00 2001 From: Masum Reza <50095635+JohnRTitor@users.noreply.github.com> Date: Fri, 27 Oct 2023 14:45:00 +0530 Subject: [PATCH 4/4] Fix a bug and organize the code a bit --- projects/File_Organizer/main.py | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/projects/File_Organizer/main.py b/projects/File_Organizer/main.py index da41d050..c8f0a0ac 100644 --- a/projects/File_Organizer/main.py +++ b/projects/File_Organizer/main.py @@ -8,19 +8,18 @@ def main(): args = parse_arguments() check_directory(args.directory_path) - # log if verbose is enabled - log_format = "%(message)s" # This will only log the message content, without any prefix - logging.basicConfig(level=logging.INFO if args.verbose else logging.WARNING, format=log_format) + setup_logging(args.verbose) organize_directory(args.directory_path) # Catch any exceptions that may occur - except ValueError as e: + except Exception as e: print(e) def parse_arguments(): + # Parse the arguments from cli, order is irrelevant parser = argparse.ArgumentParser(description="Organize files in a directory based on their extensions.") - parser.add_argument("directory_path", type=str, help="Path of the directory to be organized") - parser.add_argument("-v", "--verbose", action="store_true", help="Enable verbose output") + parser.add_argument("directory_path", type=str, help="Path of the directory to be organized") # Required argument + parser.add_argument("-v", "--verbose", action="store_true", help="Enable verbose output") # Optional argument return parser.parse_args() def check_directory(directory_path): @@ -33,15 +32,20 @@ def check_directory(directory_path): if not os.access(directory_path, os.W_OK): raise ValueError(f"'{directory_path}' is not writable.") +def setup_logging(verbose): + log_level = logging.INFO if verbose else logging.WARNING + log_format = "%(message)s" + logging.basicConfig(level=log_level, format=log_format) + def organize_directory(directory_path): categories = { - "Music": (".mp3", ".wav", ".flac", ".m4a", ".aac", ".ogg", ".oga" ".wma", ".mid"), - "Videos": (".mp4", ".avi", ".mkv", ".mpeg", ".wmv", ".vob", ".flv", ".mov", ".3gp", ".webm"), - "Source Files": (".py", ".c", ".cpp", ".java", ".js", ".cs", ".html", ".css", ".php", ".json", ".xml", ".sql", ".db"), - "Executables": (".exe", ".msi", ".sh", ".bat", ".apk", ".jar", ".deb", ".run", ".bin", ".dmg", ".iso"), - "Pictures": (".jpg", ".jpeg", ".png", ".gif", ".bmp", ".svg", ".webp", ".psd", ".ai", ".ico"), - "Documents": (".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".txt", ".md", ".odt", ".ods", ".odp", ".csv", ".rtf"), - "Compressed": (".zip", ".rar", ".tar", ".gz", ".7z", ".bz2", ".xz", ".z", ".lz"), + "Music": (".mp3", ".wav", ".flac", ".m4a", ".aac", ".ogg", ".oga", ".wma", ".mid",), + "Videos": (".mp4", ".avi", ".mkv", ".mpeg", ".wmv", ".vob", ".flv", ".mov", ".3gp", ".webm",), + "Source Files": (".py", ".c", ".cpp", ".java", ".js", ".cs", ".html", ".css", ".php", ".json", ".xml", ".sql", ".db",), + "Executables": (".exe", ".msi", ".sh", ".bat", ".apk", ".jar", ".deb", ".run", ".bin", ".dmg", ".iso",), + "Pictures": (".jpg", ".jpeg", ".png", ".gif", ".bmp", ".svg", ".webp", ".psd", ".ai", ".ico",), + "Documents": (".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".txt", ".md", ".odt", ".ods", ".odp", ".csv", ".rtf",), + "Compressed": (".zip", ".rar", ".tar", ".gz", ".7z", ".bz2", ".xz", ".z", ".lz",), "Torrents": (".torrent",), }