From 51c557d228dc88edb6f764f3b95ef9120813497b Mon Sep 17 00:00:00 2001 From: Sarahtonin Date: Mon, 20 Apr 2026 19:58:29 +0200 Subject: [PATCH] Added FileHistoryName to config, allowing an input and output dir to be the same and stopping recursion by saving the new file name. Also fixed hour, minute, second, and so to be at least 2 wide (19:2:3 => 19:02:03) --- .Github/README.md | 2 ++ Config.toml | 7 ++--- SaraSortd.py | 67 ++++++++++++++++++++++++++++++++++++----------- 3 files changed, 58 insertions(+), 18 deletions(-) diff --git a/.Github/README.md b/.Github/README.md index 593543f..5688f34 100644 --- a/.Github/README.md +++ b/.Github/README.md @@ -103,6 +103,8 @@ LogFileName = "[y].[m].[d]._*" # Name for log files. DirConfName = ".@Config" # Name for config files for directories. +FileHistoryName = ".@History" # Name for file history files. This keeps track of sorted files if an input and output are the same directory. + [Log] All = "[h]:[n]:[s] | " # What to put at the start of all lines in Log file. diff --git a/Config.toml b/Config.toml index 71ee501..dcad170 100644 --- a/Config.toml +++ b/Config.toml @@ -1,7 +1,7 @@ Title = "SaraSortd Config" SafeMode = 1 SilentMode = 0 -CheckInput = 10 +CheckInput = 5 DotFiles = 0 Logging = 1 OverwriteDirConf = 0 @@ -21,7 +21,7 @@ Second = "[s]" VarCall = "%%" [DirectoryPaths] -RootDir = "Unset" +RootDir = "/home/sarah/TestDir" InputDir = [ "%RootDir%/Input" ] OutputDir = [ "%RootDir%/Output" ] LogDir = "%RootDir%/.Logs" @@ -30,12 +30,13 @@ FailedDir = "%RootDir%/.Failed" [Names] LogFileName = "[y].[m].[d]" DirConfName = ".@Config" +FileHistoryName = ".@History" [Log] All = "[h]:[n]:[s] | " Start = "Started SaraSortd." NotStart = "Error: Failed to start SaraSortd." -Stop = "\nStopped SaraSortd." +Stop = "Stopped SaraSortd.\n" MatchPattern = "Checking %%." Sorted = "Sorted %%." NotSorted = "Error: Failed to sort %%. No valid output directory." diff --git a/SaraSortd.py b/SaraSortd.py index 9435f49..70dc726 100644 --- a/SaraSortd.py +++ b/SaraSortd.py @@ -166,11 +166,11 @@ def Parse( ConfVars["OrgFileName"]: str(OrgFileName), ConfVars["OrgFileType"]: str(OrgFileType), ConfVars["Year"]: str(Now.year), - ConfVars["Month"]: str(Now.month), - ConfVars["Day"]: str(Now.day), - ConfVars["Hour"]: str(Now.hour), - ConfVars["Minute"]: str(Now.minute), - ConfVars["Second"]: str(Now.second), + ConfVars["Month"]: str(Now.month).rjust(2, "0"), + ConfVars["Day"]: str(Now.day).rjust(2, "0"), + ConfVars["Hour"]: str(Now.hour).rjust(2, "0"), + ConfVars["Minute"]: str(Now.minute).rjust(2, "0"), + ConfVars["Second"]: str(Now.second).rjust(2, "0"), ConfVars["VarCall"]: str(VarCall), } @@ -188,6 +188,23 @@ def Parse( def Clone(Source, Destination, NewName, Delete = False): + if (os.path.dirname(Source) == Destination): + FileHistoryPath = f"{Destination}/{Parse(ConfNames["FileHistoryName"], Parent = os.path.basename(Destination))}.toml" + print("FileHistoryPath:",FileHistoryPath) + + if not os.path.exists(FileHistoryPath): + with open(FileHistoryPath, "w", encoding = "utf-8") as HistoryFile: + toml.dump({"Title": f"{os.path.basename(Destination)} History", "History": []}, HistoryFile) + + HistoryFileData = toml.load(FileHistoryPath) + if (NewName not in HistoryFileData["History"]): + HistoryFileData["History"].append(NewName) + with open(FileHistoryPath, "w", encoding = "utf-8") as HistoryFile: + toml.dump(HistoryFileData, HistoryFile) + + os.rename(Source, os.path.join(Destination, NewName)) + return + Dir(Destination, Output = False, CopyConf = False) shutil.copy2(Source, Destination) @@ -364,6 +381,16 @@ def DecideNewPath(FilePath): def Sort(FilePath): NewPath = DecideNewPath(FilePath) + if NewPath is None: + Dir(Parse(String = ConfDirs["FailedDir"]), Output = False, CopyConf = False) + NewName = os.path.basename(FilePath) + Clone(FilePath, Parse(String = ConfDirs["FailedDir"]), NewName, True) + + TextOutput = Parse(String = ConfLog["NotSorted"], VarCall = FilePath) + LogWrite(TextOutput) + Speak(TextOutput) + return + NewDirPath = os.path.dirname(NewPath) NewName = os.path.basename(NewPath) @@ -373,16 +400,6 @@ def Sort(FilePath): else: Delete = False - if NewPath is None: - Dir(Parse(String = ConfDirs["FailedDir"]), Output = False, CopyConf = False) - NewName = os.path.basename(FilePath) - Clone(FilePath, Parse(String = ConfDirs["FailedDir"]), NewName, Delete) - - TextOutput = Parse(String = ConfLog["NotSorted"], VarCall = FilePath) - LogWrite(TextOutput) - Speak(TextOutput) - return - try: Clone(FilePath, NewDirPath, NewName, Delete) UpdateConf(f"{NewDirPath}/{Parse(String = ConfNames['DirConfName'], Parent = os.path.basename(NewDirPath))}.toml", "LastFile", NewName) @@ -450,11 +467,24 @@ def Main(): try: while True: for Input in ConfDirs["InputDir"]: + RecurseDir = False + InputPath = Parse(Input) if not os.path.exists(InputPath): continue + for Output in ConfDirs["OutputDir"]: + OutputPath = Parse(Output) + + if (OutputPath == InputPath): + RecurseDir = True + FileHistoryPath = f"{InputPath}/{Parse(ConfNames["FileHistoryName"], Parent = os.path.basename(InputPath))}.toml" + + if not os.path.exists(FileHistoryPath): + with open(FileHistoryPath, "w", encoding = "utf-8") as HistoryFile: + toml.dump({"Title": f"{os.path.basename(InputPath)} History", "History": [] }, HistoryFile) + for FileName in os.listdir(InputPath): FilePath = f"{InputPath}/{FileName}" @@ -462,6 +492,13 @@ def Main(): FileName = os.path.basename(FilePath) if FileName.startswith(".") and Conf["DotFiles"] == 0: continue + + if RecurseDir: + HistoryFile = toml.load(FileHistoryPath) + + if (Parse(FileName, Parent = os.path.basename(InputPath)) in HistoryFile["History"]): + continue + Sort(FilePath) time.sleep(Conf.get("CheckInput", 10))