├── LICENSE.md ├── readme.md └── file-sorter.py /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Gylan Salih 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # 🎉 File Sorter 🗂️ 2 | 3 | 4 |
5 | 6 | [![Contributors][contributors-shield]][contributors-url] 7 | [![Forks][forks-shield]][forks-url] 8 | [![Stargazers][stars-shield]][stars-url] 9 | [![Issues][issues-shield]][issues-url] 10 | [![MIT License][license-shield]][license-url] 11 | 12 |
13 | 14 | 15 | [contributors-shield]: https://custom-icon-badges.demolab.com/github/contributors/GylanSalih/OrganizeMyFiles?color=FF0000&logo=group&label=Contributors&logoColor=white&style=for-the-badge&labelColor=000000 16 | [forks-shield]: https://custom-icon-badges.demolab.com/github/forks/GylanSalih/OrganizeMyFiles?color=FF0000&logo=repo-forked&label=Forks&logoColor=white&style=for-the-badge&labelColor=000000 17 | [stars-shield]: https://custom-icon-badges.demolab.com/github/stars/GylanSalih/OrganizeMyFiles?color=FF0000&label=Stars&style=for-the-badge&logo=star&logoColor=white&labelColor=000000 18 | [issues-shield]: https://custom-icon-badges.demolab.com/github/issues/GylanSalih/OrganizeMyFiles?color=FF0000&logo=issue-opened&label=Issues&logoColor=white&labelColor=000000&style=for-the-badge& 19 | [license-shield]: https://custom-icon-badges.demolab.com/github/license/GylanSalih/OrganizeMyFiles?color=FF0000&logo=law&label=License&logoColor=white&style=for-the-badge&labelColor=000000 20 | 21 | 22 | [contributors-url]: https://github.com/GylanSalih/OrganizeMyFiles/graphs/contributors 23 | [forks-url]: https://github.com/GylanSalih/OrganizeMyFiles/network/members 24 | [stars-url]: https://github.com/GylanSalih/OrganizeMyFiles/stargazers 25 | [issues-url]: https://github.com/GylanSalih/OrganizeMyFiles/issues 26 | [license-url]: https://github.com/GylanSalih/OrganizeMyFiles/blob/main/LICENSE 27 | 28 |

29 | File Sorter Logo 30 |

31 | 32 | A user-friendly tool to automatically organize your files! This program categorizes files based on their types and places them into designated folders. Say goodbye to the hassle of manual file sorting! 😊 33 | 34 | --- 35 | 36 | ## 📋 Table of Contents 37 | - [📖 Introduction](#-introduction) 38 | - [✨ Features](#-features) 39 | - [⚙️ Installation](#️-installation) 40 | - [🚀 Usage](#-usage) 41 | - [📂 File Types](#-file-types) 42 | - [📦 Dependencies](#-dependencies) 43 | - [🔧 Configuration](#-configuration) 44 | - [📜 Logging](#-logging) 45 | - [🖼️ Screenshots](#-screenshots) 46 | - [🤝 Developers](#-developers) 47 | - [📄 License](#-license) 48 | 49 | --- 50 | 51 | ## 📖 Introduction 52 | 🎯 **File Sorter** is your go-to tool for organizing files in a folder automatically into predefined categories like Images, Documents, Videos, and more. With just a few clicks, you can transform a cluttered folder into an organized one. 🚀 53 | 54 | --- 55 | 56 | ## ✨ Features 57 | ✅ **User-Friendly GUI**: Built with `tkinter`, making it easy to use for everyone. 58 | ✅ **File Categorization**: Organizes files into categories such as Images, Documents, and Videos. 59 | ✅ **Custom Sorting**: Allows sorting by specific file types or all file types at once. 60 | ✅ **Multithreading**: Uses concurrent file processing for faster sorting. 61 | ✅ **Duplicate Handling**: Prevents overwriting by appending unique identifiers to duplicate filenames. 62 | ✅ **Empty Folder Cleanup**: Automatically removes empty folders after sorting. 63 | ✅ **Detailed Logging**: Keeps track of all operations in a log file for reference. 64 | 65 | --- 66 | 67 | ## ⚙️ Installation 68 | To set up and use the File Sorter: 69 | 70 | 1. Clone this repository: 71 | ```bash 72 | git clone https://github.com/yourusername/file-sorter.git 73 | cd file-sorter 74 | ``` 75 | 76 | 2. Install the required dependencies: 77 | 78 | 79 | 3. Run the program: 80 | ```bash 81 | python file_sorter.py 82 | ``` 83 | 84 | --- 85 | 86 | ## 🚀 Usage 87 | 1. **Launch the Program**: Run the script, and the GUI will open. 88 | 2. **Select a Folder**: Click the "Browse" button to select the folder you want to organize. 89 | 3. **Choose a File Type**: Use the dropdown menu to select a category (e.g., Images, Documents, etc.) or choose "All Files" to sort everything. 90 | 4. **Start Sorting**: Click the "Start Sorting" button. A success message will pop up once the files are sorted. 91 | 92 | --- 93 | 94 | ## 📂 File Types 95 | The following file types are supported: 96 | 97 | | **Category** | **Extensions** | 98 | |------------------------|-------------------------------------------------------------------------------| 99 | | **Images** | `.jpg`, `.jpeg`, `.png`, `.gif`, `.svg`, `.bmp`, `.webp`, `.ico`, `.tiff` | 100 | | **Documents** | `.pdf`, `.docx`, `.txt`, `.xls`, `.xlsx`, `.ppt`, `.rtf`, `.odt`, `.ods` | 101 | | **Videos** | `.mp4`, `.mkv`, `.avi`, `.mov`, `.flv`, `.webm`, `.wmv` | 102 | | **Audio** | `.mp3`, `.wav`, `.flac`, `.aac`, `.ogg`, `.m4a` | 103 | | **Archives** | `.zip`, `.rar`, `.7z`, `.tar`, `.gz`, `.iso` | 104 | | **Coding** | `.py`, `.js`, `.html`, `.css`, `.json`, `.java`, `.cpp`, `.rb`, `.php` | 105 | | **Installation Files**| `.exe`, `.msi`, `.dmg`, `.pkg`, `.deb`, `.rpm` | 106 | | **E-Books** | `.epub`, `.mobi`, `.azw`, `.pdf` | 107 | | **Fonts** | `.ttf`, `.otf`, `.woff`, `.eot` | 108 | | **Databases** | `.db`, `.sqlite`, `.sql`, `.mdb` | 109 | | **3D Models** | `.obj`, `.fbx`, `.stl`, `.dae` | 110 | | **Vector Graphics** | `.ai`, `.eps`, `.svg`, `.cdr` | 111 | | **Configurations** | `.cfg`, `.ini`, `.yaml` | 112 | | **Log Files** | `.log`, `.out` | 113 | 114 | --- 115 | 116 | ## 📦 Dependencies 117 | The program relies on the following Python modules: 118 | - `tkinter` (built-in with Python) 119 | - `requests` 120 | - `shutil` 121 | - `concurrent.futures` 122 | 123 | The script automatically installs missing dependencies. 124 | 125 | --- 126 | 127 | ## 🔧 Configuration 128 | - **Download Folder**: Select your desired folder through the GUI. 129 | - **File Type Selection**: Choose specific file categories or sort all files. 130 | - **Multithreading**: The script uses `ThreadPoolExecutor` with 4 workers by default. Adjust the `max_workers` parameter in the code for higher performance if needed. 131 | 132 | --- 133 | 134 | ## 📜 Logging 135 | All operations are logged in a file named `OrganizeMyFiles.log`. Logs include: 136 | - Successfully moved files 137 | - Duplicate files and their renamed versions 138 | - Errors encountered 139 | - Empty folders that were removed 140 | 141 | --- 142 | 143 | ## 🖼️ Screenshots 144 | Below are some screenshots of the application in action: 145 | 146 |

147 | Main Interface 148 |
149 | Figure 1: The main interface of the File Sorter 150 |

151 | 152 |

153 | File Sorting Process 154 |
155 | Figure 2: File sorting process is ended 156 |

157 | 158 | --- 159 | 160 | ## 🤝 Developers 161 | Developed by: 162 | - [Gylan Salih (Germany)](https://github.com/GylanSalih) 163 | - [Mahan Rahmani (Iran)](https://github.com/mhnrhmni) 164 | 165 | 🌟 **Thank you for using our tool! Follow us on GitHub and give us a star if you find it useful!** 🌟 166 | 167 | --- 168 | 169 | ## 📄 License 170 | This project is licensed under the [MIT License](LICENSE). You are free to use, modify, and distribute this software. 171 | 172 | --- 173 | 174 | 🚀 **Enjoy organizing your files with ease!** 175 | ``` 176 | -------------------------------------------------------------------------------- /file-sorter.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import sys 3 | 4 | # Function to install packages using pip 5 | def install(package): 6 | """Install a package using pip.""" 7 | subprocess.check_call([sys.executable, "-m", "pip", "install", package]) 8 | 9 | # Check and install required packages 10 | required_packages = ['requests'] 11 | 12 | for package in required_packages: 13 | try: 14 | __import__(package) 15 | except ImportError: 16 | install(package) 17 | 18 | import os 19 | import shutil 20 | import logging 21 | import tkinter as tk 22 | from tkinter import ttk, filedialog, messagebox 23 | import webbrowser 24 | from concurrent.futures import ThreadPoolExecutor 25 | 26 | # Logging configuration 27 | logging.basicConfig(filename='OrganizeMyFiles.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') 28 | 29 | # Dictionary for file types 30 | file_types = { 31 | 'Images': ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp', '.svg', '.tiff', '.ico', '.psd', '.raw', '.heic'], 32 | 'Documents': ['.pdf', '.docx', '.doc', '.txt', '.xls', '.xlsx', '.ppt', '.pptx', '.odt', '.ods', '.odp', '.rtf', '.tex'], 33 | 'Videos': ['.mp4', '.mkv', '.avi', '.mov', '.wmv', '.flv', '.webm', '.mpeg', '.3gp'], 34 | 'Audio': ['.mp3', '.wav', '.aac', '.flac', '.ogg', '.wma', '.m4a', '.aiff'], 35 | 'Archives': ['.zip', '.rar', '.tar', '.gz', '.7z', '.bz2', '.xz', '.iso', '.cab'], 36 | 'Coding': ['.json', '.scss', '.css', '.html', '.js', '.py', '.java', '.c', '.cpp', '.php', '.xml', '.sql', '.rb', '.go', '.sh', '.ts', '.md'], 37 | 'Installation Files': ['.msi', '.exe', '.dmg', '.pkg', '.deb', '.rpm', '.app', '.bat', '.sh', '.bin'], 38 | 'E-Books': ['.epub', '.mobi', '.azw', '.azw3', '.djvu', '.ibooks'], 39 | 'Fonts': ['.ttf', '.otf', '.woff', '.woff2', '.eot', '.fon'], 40 | 'Databases': ['.db', '.sqlite', '.sql', '.mdb', '.accdb'], 41 | 'CAD Files': ['.dwg', '.dxf', '.step', '.stl', '.igs', '.iges'], 42 | '3D Models': ['.obj', '.fbx', '.dae', '.3ds', '.blend'], 43 | 'Vector Graphics': ['.ai', '.eps', '.svg', '.cdr'], 44 | 'Design Projects': ['.psd', '.ai', '.xd', '.fig', '.sketch'], 45 | 'Saved Web Pages': ['.html', '.htm', '.mhtml', '.webarchive'], 46 | 'Configurations': ['.ini', '.cfg', '.conf', '.yaml', '.yml'], 47 | 'Log Files': ['.log', '.out'], 48 | 'PDF Files': ['.pdf'], 49 | 'Miscellaneous': [] 50 | } 51 | 52 | # Function to sort files 53 | def sort_files(download_folder, file_type_selection): 54 | try: 55 | # Using ThreadPoolExecutor for concurrent file processing 56 | with ThreadPoolExecutor(max_workers=4) as executor: 57 | for filename in os.listdir(download_folder): 58 | file_path = os.path.join(download_folder, filename) 59 | if os.path.isfile(file_path): 60 | executor.submit(process_file, file_path, download_folder, file_type_selection) 61 | 62 | remove_empty_folders(download_folder) 63 | messagebox.showinfo("Success", "Files sorted successfully!") 64 | 65 | except Exception as e: 66 | logging.error(f"Error occurred: {e}") 67 | messagebox.showerror("Error", f"An error occurred: {e}") 68 | 69 | # Function to process individual file 70 | def process_file(file_path, download_folder, file_type_selection): 71 | file_ext = os.path.splitext(file_path)[1].lower() 72 | destination_folder = None 73 | 74 | for folder, extensions in file_types.items(): 75 | if file_ext in extensions: 76 | if file_type_selection == "All Files" or file_type_selection == folder: 77 | destination_folder = os.path.join(download_folder, folder) 78 | break 79 | 80 | if destination_folder: 81 | if not os.path.exists(destination_folder): 82 | os.makedirs(destination_folder) 83 | 84 | dest_file_path = os.path.join(destination_folder, os.path.basename(file_path)) 85 | if os.path.exists(dest_file_path): 86 | base_name, ext = os.path.splitext(os.path.basename(file_path)) 87 | counter = 1 88 | new_filename = f"{base_name}_{counter}{ext}" 89 | while os.path.exists(os.path.join(destination_folder, new_filename)): 90 | counter += 1 91 | new_filename = f"{base_name}_{counter}{ext}" 92 | dest_file_path = os.path.join(destination_folder, new_filename) 93 | 94 | shutil.move(file_path, dest_file_path) 95 | logging.info(f'Successfully moved: {os.path.basename(file_path)} -> {destination_folder}') 96 | 97 | # Function to remove empty folders 98 | def remove_empty_folders(path): 99 | if not os.path.isdir(path): 100 | return 101 | 102 | for folder in os.listdir(path): 103 | folder_path = os.path.join(path, folder) 104 | if os.path.isdir(folder_path): 105 | remove_empty_folders(folder_path) 106 | if not os.listdir(folder_path): 107 | os.rmdir(folder_path) 108 | logging.info(f'Removed empty folder: {folder_path}') 109 | 110 | # Function to choose download folder 111 | def choose_folder(): 112 | folder = filedialog.askdirectory() 113 | if folder: 114 | folder_path.set(folder) 115 | 116 | # Function to start sorting files 117 | def start_sorting(): 118 | folder = folder_path.get() 119 | file_type_selection = file_type_var.get() 120 | if folder: 121 | sort_files(folder, file_type_selection) 122 | else: 123 | messagebox.showwarning("Warning", "Please select a folder first.") 124 | 125 | # Function to open link in web browser 126 | def open_link(url): 127 | webbrowser.open_new(url) 128 | 129 | # Create GUI 130 | root = tk.Tk() 131 | root.title("File Sorter") 132 | 133 | style = ttk.Style() 134 | style.configure("TButton", font=('Helvetica', 12)) 135 | style.configure("TLabel", font=('Helvetica', 12)) 136 | style.configure("TEntry", font=('Helvetica', 12)) 137 | style.configure("TCombobox", font=('Helvetica', 12)) 138 | 139 | folder_path = tk.StringVar() 140 | file_type_var = tk.StringVar() 141 | 142 | main_frame = ttk.Frame(root, padding="20") 143 | main_frame.pack(pady=20, padx=20, fill=tk.BOTH, expand=True) 144 | 145 | center_frame = ttk.Frame(main_frame) 146 | center_frame.pack(padx=20, pady=20) 147 | 148 | label = ttk.Label(center_frame, text="Select Download Folder:") 149 | label.pack(side=tk.LEFT) 150 | 151 | entry = ttk.Entry(center_frame, textvariable=folder_path, width=50) 152 | entry.pack(side=tk.LEFT, padx=10) 153 | 154 | browse_button = ttk.Button(center_frame, text="Browse", command=choose_folder) 155 | browse_button.pack(side=tk.LEFT) 156 | 157 | # Add dropdown menu for selecting file type 158 | file_type_options = ["All Files", "Images", "Documents", "Videos", "Audio", "Archives", "Coding", "Installation Files", "E-Books", "Fonts", "Databases", "CAD Files", "3D Models", "Vector Graphics", "Design Projects", "Saved Web Pages", "Configurations", "Log Files", "PDF Files", "Miscellaneous"] 159 | file_type_var.set("All Files") 160 | file_type_menu = ttk.Combobox(center_frame, textvariable=file_type_var, values=file_type_options, state="readonly") 161 | file_type_menu.pack(side=tk.LEFT, padx=10) 162 | 163 | sort_button = ttk.Button(root, text="Start Sorting", command=start_sorting) 164 | sort_button.pack(pady=10) 165 | 166 | # Add developer names with hyperlinks 167 | footer_frame = ttk.Frame(root, padding="10") 168 | footer_frame.pack(side=tk.BOTTOM, fill=tk.X) 169 | 170 | # GitHub links for developers 171 | creator_1_url = "https://github.com/GylanSalih" 172 | creator_2_url = "https://github.com/mhnrhmni" 173 | 174 | developers_label = ttk.Label(footer_frame, text="Developers:", font=('Helvetica', 12)) 175 | developers_label.pack(side=tk.LEFT, padx=5) 176 | 177 | creator_1_link = ttk.Label(footer_frame, text="Gylan Salih (Germany)", foreground="blue", cursor="hand2", font=('Helvetica', 12)) 178 | creator_1_link.pack(side=tk.LEFT, padx=5) 179 | creator_1_link.bind("", lambda e: open_link(creator_1_url)) 180 | 181 | creator_2_link = ttk.Label(footer_frame, text="Mahan Rahmani (Iran)", foreground="blue", cursor="hand2", font=('Helvetica', 12)) 182 | creator_2_link.pack(side=tk.LEFT, padx=5) 183 | creator_2_link.bind("", lambda e: open_link(creator_2_url)) 184 | 185 | # Add thank you message and request for GitHub stars 186 | thanks_message = ttk.Label(footer_frame, text="Thank you for using our tool! Please follow us and give us a star on GitHub ⭐", font=('Helvetica', 12)) 187 | thanks_message.pack(side=tk.LEFT, padx=20) 188 | 189 | root.mainloop() 190 | --------------------------------------------------------------------------------