├── 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 |
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 |
148 |
149 | Figure 1: The main interface of the File Sorter
150 |
151 |
152 |
153 |
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 |
--------------------------------------------------------------------------------