Skip to content

Instantly share code, notes, and snippets.

@themacmarketer
Created July 22, 2023 04:20
Show Gist options
  • Select an option

  • Save themacmarketer/5b48b660b0e5f0501916ba3a6d55b7d9 to your computer and use it in GitHub Desktop.

Select an option

Save themacmarketer/5b48b660b0e5f0501916ba3a6d55b7d9 to your computer and use it in GitHub Desktop.
This is a Python script that uses the wxPython library to create a graphical user interface (GUI) application for sorting files in a specified directory based on a defined set of topics and associated keywords.
/*
This is a Python script that uses the wxPython library to create a graphical user interface (GUI) application for sorting files in a specified directory based on a defined set of topics and associated keywords.
At the start, several libraries are imported: `os` and `shutil` for file and directory manipulation, `wx` for creating the GUI, `json` for reading and writing JSON data, and `re` for regular expression operations.
A constant named `TOPICS_FILE` is defined, which is the name of the JSON file that stores topics and their associated keywords.
The `load_topics` function checks if the `TOPICS_FILE` exists, and if it does, opens the file and loads the JSON data into a Python dictionary. If the file does not exist, it returns an empty dictionary.
The `MainFrame` class is the main application window. It contains controls for directory selection (`DirPickerCtrl`), a text area to display the topics and keywords (`TextCtrl`), and three buttons ("Process Files", "Undo Sort", and "Exit").
The `process_files` method sorts files in the chosen directory. For each file, it compares the file name (sanitized to lower case and without special characters) against the keywords for each topic. If a match is found, the file is moved to a subdirectory named after the matched topic. If no match is found, the file is moved to a "Miscellaneous" subdirectory.
The `undo_sort` method undoes the sorting operation by moving all files back to the original directory and removing the created subdirectories.
The `sanitize` method is a helper method that removes special characters from a string and converts it to lower case.
The `on_exit` method is bound to the Exit button and closes the application.
The script concludes with a block that creates an instance of the `MainFrame` and starts the wxPython event loop, causing the application window to appear on the screen.
*/
import os
import wx
import json
import shutil
import re
# Constants
TOPICS_FILE = "topics.json"
# Load topics and keywords from the JSON file
def load_topics() -> dict:
if os.path.exists(TOPICS_FILE):
with open(TOPICS_FILE, "r") as file:
return json.load(file)
else:
return {}
class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="File Processing App", size=(600,400))
# Set the panel
self.panel = wx.Panel(self)
# Folder Path
self.folderPath = wx.DirPickerCtrl(self.panel, path=os.getcwd())
# Topics text
self.topicText = wx.TextCtrl(self.panel, style=wx.TE_MULTILINE)
self.topicText.SetValue(json.dumps(load_topics(), indent=4))
# Process Button
self.processBtn = wx.Button(self.panel, label="Process Files")
self.processBtn.Bind(wx.EVT_BUTTON, self.process_files)
# Undo Button
self.undoBtn = wx.Button(self.panel, label="Undo Sort")
self.undoBtn.Bind(wx.EVT_BUTTON, self.undo_sort)
# Exit Button
self.exitBtn = wx.Button(self.panel, label="Exit")
self.exitBtn.Bind(wx.EVT_BUTTON, self.on_exit)
# Set sizer
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
self.mainSizer.Add(self.folderPath, 0, wx.ALL|wx.EXPAND, 5)
self.mainSizer.Add(self.topicText, 0, wx.ALL|wx.EXPAND, 5)
self.mainSizer.Add(self.processBtn, 0, wx.ALL|wx.CENTER, 5)
self.mainSizer.Add(self.undoBtn, 0, wx.ALL|wx.CENTER, 5)
self.mainSizer.Add(self.exitBtn, 0, wx.ALL|wx.CENTER, 5)
self.panel.SetSizer(self.mainSizer)
def process_files(self, event):
folder_path = self.folderPath.GetPath()
for file in os.listdir(folder_path):
file_path = os.path.join(folder_path, file)
if os.path.isfile(file_path):
sanitized_file = self.sanitize(file)
matched_topic = None
for topic, keywords in load_topics().items():
if any(self.sanitize(keyword) in sanitized_file for keyword in keywords):
matched_topic = topic
break
if matched_topic:
topic_dir = os.path.join(folder_path, matched_topic)
os.makedirs(topic_dir, exist_ok=True)
shutil.move(file_path, os.path.join(topic_dir, file))
else:
miscellaneous_dir = os.path.join(folder_path, "Miscellaneous")
os.makedirs(miscellaneous_dir, exist_ok=True)
shutil.move(file_path, os.path.join(miscellaneous_dir, file))
def undo_sort(self, event):
current_dir = self.folderPath.GetPath()
for root, dirs, files in os.walk(current_dir, topdown=False):
for file in files:
file_path = os.path.join(root, file)
shutil.move(file_path, os.path.join(current_dir, file))
for dir_name in dirs:
dir_path = os.path.join(root, dir_name)
if not os.listdir(dir_path):
os.rmdir(dir_path)
def sanitize(self, name: str) -> str:
return re.sub(r'[_\W]+', ' ', name).lower()
def on_exit(self, event):
self.Close()
if __name__ == "__main__":
app = wx.App(False)
frame = MainFrame()
frame.Show()
app.MainLoop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment