From f0b2ec62ef9550b8637715de556bf27b576608e8 Mon Sep 17 00:00:00 2001 From: Sarahtonin Date: Wed, 29 Apr 2026 07:50:04 +0200 Subject: [PATCH] Added function to InputDirConf, including pattern and if the input should sort directories or not. Also added zipping functions to move said directories. TODO: Add unzipping functions. --- .Github/README.md | 25 ++++++++++-- GlobalConf.toml | 7 +++- InputDirConf.toml | 7 +++- OutputDirConf.toml | 2 +- SaraSortd.py | 95 +++++++++++++++++++++++++++++++++++----------- 5 files changed, 106 insertions(+), 30 deletions(-) diff --git a/.Github/README.md b/.Github/README.md index 365c729..3ce5b86 100644 --- a/.Github/README.md +++ b/.Github/README.md @@ -1,5 +1,5 @@ # SaraSortd -(Version = "5.1") +(Version = "6.0") A python daemon that can automatically sort your files to your liking without using AI. @@ -48,7 +48,7 @@ Here's a step-by-step tutorial (in case you don't want to watch the video). ``` Title = "SaraSortd Config" # NOTE: Do not change the title. This is so that the program knows which config file is which. -Version = "5.1" # Just the version number for the config file. +Version = "6.0" # Just the version number for the config file. SafeMode = 1 # If SaraSortd should stop if an error with the config appears. 1 is stop, 0 is continue. @@ -128,6 +128,15 @@ ValueSet = "Set: %%." # When a value in a config is set. Unset = "Error: %% is not set." # When a value isn't set. # %% here is just the parameter who's value was either "Unset" or None. E.G: "RootDir". + +Zipping = "Zipping: %%." # When a directory is zipped. +# %% here is the path to the directory being zipped. + +Unzipping = "Unzipping: %%." # When a directory gets unzipped. +# %% is the path to the directory being unzipped. + +NoPermission = "Error: No permission to %%." # When SaraSortd lacks permission to do something. +# %% is the action that the program had no permission to do. E.G. "remove directory /home/bob/exampledir". ``` @@ -138,7 +147,7 @@ The output directory config references the SaraSortd config (GlobalConf.toml). T ``` Title = "Unset" # NOTE: Do not change the title. This is so that the program knows which config file is which. -Version = "5.1" # The version number of the config. +Version = "6.0" # The version number of the config. LastFile = "Unset" # The last file that was sorted to this directory. It gets automatically updated whenever a file gets sorted to this directory. @@ -186,7 +195,15 @@ Overwrite = 1 # Whether this specific file type can be overwritten by others of ``` Title = "Unset" # NOTE: Do not change the title. This is so that the program knows which config file is which. -Version = "5.1" +Version = "6.0" ParentDir = "Unset" # The name of this directory. It gets automatically updated when this config gets copied to an output directory. + +SortDirs = 0 + +[[Files]] # The double brackets means that you can add multiple types of files to be sorted here. Just copy [[Files]] and all the parameters under it, and paste it under or over this section, then you may change the values of the new parameters. + +Pattern = "*" # A pattern used to decide if a file should be sorted or not. * is a wildcard; ? is a one-character wildcard. E.G: if Pattern is "*.png", all files ending with .png in this directory will try to be sorted. + +CaseSensitive = 0 # Whether Pattern is case-sensitive or not. If CaseSensitive = 1 and your pattern is "*.PNG", then a file named "example.png" won't be sorted. ``` diff --git a/GlobalConf.toml b/GlobalConf.toml index c0c094c..7b9fcc0 100644 --- a/GlobalConf.toml +++ b/GlobalConf.toml @@ -1,5 +1,5 @@ Title = "SaraSortd Config" -Version = "5.1" +Version = "6.0" SafeMode = 1 SilentMode = 0 CheckInput = 5 @@ -22,7 +22,7 @@ Second = "[s]" VarCall = "%%" [DirectoryPaths] -RootDir = "Unset" +RootDir = "C:/Users/StigOscarAadalen-Aas/OneDrive - Telemark fylkeskommune/Desktop/Testdir" InputDir = [ "%RootDir%/Input" ] OutputDir = [ "%RootDir%/Output" ] LogDir = "%RootDir%/.Logs" @@ -44,3 +44,6 @@ Sorted = "Sorted %%." NotSorted = "Error: Failed to sort %%. No valid output directory." ValueSet = "Set %%." Unset = "Error: %% is not set." +Zipping = "Zipping: %%." +Unzipping = "Unzipping: %%." +NoPermission = "Error: No permission to %%." diff --git a/InputDirConf.toml b/InputDirConf.toml index 6def304..75a695f 100644 --- a/InputDirConf.toml +++ b/InputDirConf.toml @@ -1,3 +1,8 @@ Title = "Unset" -Version = "5.1" +Version = "6.0" ParentDir = "Unset" +SortDirs = 0 + +[[Files]] +Pattern = "*" +CaseSensitive = 0 diff --git a/OutputDirConf.toml b/OutputDirConf.toml index 3afb550..66958c3 100644 --- a/OutputDirConf.toml +++ b/OutputDirConf.toml @@ -1,5 +1,5 @@ Title = "Unset" -Version = "5.1" +Version = "6.0" LastFile = "Unset" ParentDir = "Unset" ValidInputDirs = ["*"] diff --git a/SaraSortd.py b/SaraSortd.py index c342a92..fbfc834 100644 --- a/SaraSortd.py +++ b/SaraSortd.py @@ -6,7 +6,7 @@ import shutil import time import toml -# Version = "5.1" +# Version = "6.0" ConfPath = "./GlobalConf.toml" @@ -217,26 +217,44 @@ def Clone(Source, Destination, NewName, Delete = False): os.remove(Source) -def Dir(Path, Output = True, CopyConf = True): +def Dir(Path, Output = True, CopyConf = "OutputDirConf.toml"): ParentName = os.path.basename(Path) os.makedirs(Path, exist_ok=True) if CopyConf: - NewOutDirConf = f"{Parse(String = ConfNames['OutDirConfName'], Path = ConfPath, Parent = ParentName)}.toml" - if Conf["OverwriteDirConf"] == 1 or not os.path.exists( - os.path.join(f"{Path}/{NewOutDirConf}") - ): - Clone("OutputDirConf.toml", Path, NewOutDirConf) - UpdateConf( - f"{Path}/{Parse(String = ConfNames['OutDirConfName'], Path = ConfPath, Parent = ParentName)}.toml", - "ParentDir", - ParentName, - ) - UpdateConf( - f"{Path}/{Parse(String = ConfNames['OutDirConfName'], Path = ConfPath, Parent = ParentName)}.toml", - "Title", - f"{ParentName} Config", - ) + if "Out" in CopyConf: + NewDirConf = f"{Parse(String = ConfNames['OutDirConfName'], Path = ConfPath, Parent = ParentName)}.toml" + + if Conf["OverwriteDirConf"] == 1 or not os.path.exists(os.path.join(f"{Path}/{NewDirConf}")): + Clone(CopyConf, Path, NewDirConf) + UpdateConf( + f"{Path}/{Parse(String = ConfNames['OutDirConfName'], Path = ConfPath, Parent = ParentName)}.toml", + "ParentDir", + ParentName, + ) + + UpdateConf( + f"{Path}/{Parse(String = ConfNames['OutDirConfName'], Path = ConfPath, Parent = ParentName)}.toml", + "Title", + f"{ParentName} Config", + ) + + if "In" in CopyConf: + NewDirConf = f"{Parse(String = ConfNames['InDirConfName'], Path = ConfPath, Parent = ParentName)}.toml" + + if Conf["OverwriteDirConf"] == 1 or not os.path.exists(os.path.join(f"{Path}/{NewDirConf}")): + Clone(CopyConf, Path, NewDirConf) + UpdateConf( + f"{Path}/{Parse(String = ConfNames['InDirConfName'], Path = ConfPath, Parent = ParentName)}.toml", + "ParentDir", + ParentName, + ) + + UpdateConf( + f"{Path}/{Parse(String = ConfNames['InDirConfName'], Path = ConfPath, Parent = ParentName)}.toml", + "Title", + f"{ParentName} Config", + ) if Output: ParsedPath = Parse(String = Path) @@ -432,7 +450,7 @@ def Init(): if Start: for InputDir in ConfDirs["InputDir"]: InputDir = Parse(String = InputDir, Path = ConfPath, Parent = os.path.basename(os.path.dirname(InputDir))) - Dir(InputDir, Output = False, CopyConf = False) + Dir(InputDir, Output = False, CopyConf = "InputDirConf.toml") for Output in ConfDirs["OutputDir"]: Output = Parse(String = Output, Parent = os.path.basename(os.path.dirname(Output))) @@ -477,6 +495,9 @@ def Main(): if not os.path.exists(InputPath): continue + InputDirConfPath = f"{InputPath}/{Parse(ConfNames["InDirConfName"], Parent = os.path.basename(InputPath))}.toml" + InputDirConf = toml.load(InputDirConfPath) + for Output in ConfDirs["OutputDir"]: OutputPath = Parse(Output) @@ -490,11 +511,41 @@ def Main(): for FileName in os.listdir(InputPath): FilePath = f"{InputPath}/{FileName}" + if os.path.isdir(FilePath) and InputDirConf["SortDirs"] == 0: + continue - if os.path.isfile(FilePath): - FileName = os.path.basename(FilePath) - if FileName.startswith(".") and Conf["DotFiles"] == 0: - continue + FileName = os.path.basename(FilePath) + if FileName.startswith(".") and Conf["DotFiles"] == 0: + continue + + for ConfFile in InputDirConf["Files"]: + if ConfFile["CaseSensitive"] == 1: + Match = fnmatch.fnmatchcase(FileName, Parse(ConfFile["Pattern"], Parent = os.path.basename(InputPath))) + + else: + Match = fnmatch.fnmatchcase(FileName.lower(), (Parse(ConfFile["Pattern"], Parent = os.path.basename(InputPath))).lower()) + + if Match: + break + + if Match: + if os.path.isdir(FilePath) and InputDirConf["SortDirs"] == 1: + TextOutput = Parse(String = ConfLog["Zipping"], VarCall = FilePath) + LogWrite(TextOutput) + Speak(TextOutput) + + shutil.make_archive(FilePath, "zip", FilePath) + + try: + os.rmdir(FilePath) + + except PermissionError: + TextOutput = Parse(String = ConfLog["NoPermission"], VarCall = f"remove directory {InputPath}/{FileName}") + LogWrite(TextOutput) + Speak(TextOutput) + continue + + FilePath = f"{FilePath}.zip" if RecurseDir: HistoryFile = toml.load(FileHistoryPath)