├── .idea ├── .gitignore ├── folder-automation.iml ├── inspectionProfiles │ └── profiles_settings.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── README.md ├── __pycache__ └── utils.cpython-38.pyc ├── config.json ├── main.py ├── requirements.txt └── utils.py /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/folder-automation.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # folder-automation 2 | 3 | ## A Smart, Configurable and Cross-Platform piece of software that runs on all operating systems 4 | 5 | --- 6 | 7 | ### This software aims to solve the clutter in **any** of your folders by moving them to their respective folders 8 | 9 | --- 10 | 11 | ## Features 12 | 13 | 1. Cross-Platform 14 | 2. Configurable 15 | 3. Consumes Little Memory 16 | 17 | --- 18 | 19 | ## Installation Instructions 20 | 21 | ```terminal 22 | git clone https://github.com/P-arag/folder-automation 23 | cd folder-automation 24 | pip install -r requirements.txt 25 | python main.py 26 | ``` 27 | 28 | ## Configure the `config.json` according to your needs 29 | 30 | # Happy Hacking!! :grin: :rocket: 31 | -------------------------------------------------------------------------------- /__pycache__/utils.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/P-arag/folder-automation/583020d2564d00cd0140552336b5f1eb0db384a1/__pycache__/utils.cpython-38.pyc -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "watch_directory": "~/Downloads", 3 | "move_folders": [ 4 | { 5 | "location": "~/Pictures", 6 | "print_text": "Images Detected", 7 | "Xtensions": ["jpg", "jpeg", "png", "gif"], 8 | "sleep": 2, 9 | "move_this_file?": true 10 | }, 11 | { 12 | "location": "~/Documents", 13 | "print_text": "Document Detected", 14 | "Xtensions": ["docx", "txt", "pdf"], 15 | "sleep": 2, 16 | "move_this_file?": true 17 | }, 18 | { 19 | "location": "~/Music", 20 | "print_text": "Audio files detected", 21 | "Xtensions": ["mp3", "wav"], 22 | "sleep": 2, 23 | "move_this_file?": true 24 | }, 25 | { 26 | "location": "~/Videos", 27 | "print_text": "Videos Detected", 28 | "Xtensions": ["mp4", "avi", "mpv", "ogg"], 29 | "sleep": 2, 30 | "move_this_file?": true 31 | }, 32 | { 33 | "location": "~/Code", 34 | "print_text": "Program Files Detected", 35 | "Xtensions": ["py", "json", "js", "c", "cs", "cpp", "java", "go"], 36 | "sleep": 2, 37 | "move_this_file?": true 38 | }, 39 | { 40 | "location": "~/Public", 41 | "print_text": "Zip files detected", 42 | "Xtensions": ["zip"], 43 | "sleep": 100, 44 | "move_this_file?": true 45 | }, 46 | { 47 | "location": "...", 48 | "print_text": "Large files detected, not doing anything", 49 | "Xtensions": ["tar", "gz", "tar.gz", "deb"], 50 | "sleep": 0, 51 | "move_this_file?": false 52 | } 53 | ] 54 | } -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | import time 4 | from pprint import pprint 5 | from watchdog.observers import Observer 6 | from watchdog.events import FileSystemEventHandler 7 | from utils import * 8 | 9 | 10 | class OnMyWatch: 11 | def __init__(self, watch_directory): 12 | self.observer = Observer() 13 | self.watch_directory = os.path.expanduser(watch_directory) 14 | print(f"WatchDog Watching {self.watch_directory}") 15 | 16 | def run(self): 17 | event_handler = Handler() 18 | self.observer.schedule( 19 | event_handler, self.watch_directory, recursive=True) 20 | self.observer.start() 21 | try: 22 | while True: 23 | time.sleep(5) 24 | except: 25 | self.observer.stop() 26 | print(" Observer Stopped") 27 | 28 | self.observer.join() 29 | 30 | 31 | class Handler(FileSystemEventHandler): 32 | @staticmethod 33 | def on_any_event(event): 34 | print(event.event_type+" "+event.src_path) 35 | 36 | if event.is_directory: 37 | return None 38 | elif event.event_type == 'created': 39 | print("*created "+event.src_path) 40 | for folder_iterable in data["move_folders"]: 41 | extensions = ["." + extension for extension in folder_iterable["Xtensions"]] 42 | if event.src_path.endswith(tuple(extensions)): 43 | print(folder_iterable["print_text"]) 44 | if folder_iterable["move_this_file?"]: 45 | time.sleep(folder_iterable["sleep"]) 46 | move_file(event.src_path, folder_iterable["location"]) 47 | print("moved") 48 | print(os.listdir(os.path.expanduser(folder_iterable["location"]))) 49 | break 50 | else: 51 | print(folder_iterable["print_text"]) 52 | break 53 | 54 | 55 | 56 | if __name__ == '__main__': 57 | data = json.load(open("./config.json")) 58 | watch = OnMyWatch(data["watch_directory"]) 59 | watch.run() 60 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | watchdog~=2.0.2 -------------------------------------------------------------------------------- /utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | from os.path import * 4 | 5 | 6 | def move_file(src: str, where: str) -> None: 7 | print("Moving %s to %s" % (src, where)) 8 | # print(os.listdir(os.path.expanduser(where))) 9 | if check_if_exists(src, where): 10 | print(f"Oops, {src} file already exists in {where}") 11 | new_file_name = newname_if_present(src, where) 12 | # new_file_name = basename(new_file_name) 13 | print("mvfile " + new_file_name) 14 | shutil.move(src, join(expanduser(where), new_file_name)) 15 | else: 16 | shutil.move(src, join(expanduser(where), basename(src))) 17 | # os.system("mv "+os.path.expanduser(src) + " " + os.path.expanduser(where)) 18 | 19 | 20 | def check_if_exists(filename: str, where: str) -> bool: 21 | # filename = basename(filename) 22 | # is_present = exists(join(where, filename)) 23 | # print(is_present) 24 | # print(filename) 25 | # print(os.listdir(expanduser(where))) 26 | if basename(filename) in os.listdir(expanduser(where)): 27 | return True 28 | return False 29 | 30 | 31 | def newname_if_present(filename: str, where: str) -> str: 32 | new_filename = filename 33 | i = 1 34 | while True: 35 | if check_if_exists(new_filename, where): 36 | filename_without_extension = splitext(new_filename)[0] 37 | extension = "" 38 | for xtension in splitext(new_filename)[1:]: 39 | extension += xtension 40 | 41 | new_filename = "%s(%d)%s" % (filename_without_extension, i, extension) 42 | else: 43 | print(new_filename) 44 | return basename(new_filename) 45 | i += 1 46 | --------------------------------------------------------------------------------