diff --git a/.Github/README.md b/.Github/README.md index 44564ba..365c729 100644 --- a/.Github/README.md +++ b/.Github/README.md @@ -1,17 +1,10 @@ # SaraSortd -(Version 4.0) +(Version = "5.1") A python daemon that can automatically sort your files to your liking without using AI. It's made by Sarah, hence the name. :3 -The versioning for SaraSortd is like so: the first number going up means that your -previous config files won't work anymore with the new SaraSortd.py. - -The second number going up means that something has been changed, but you can still -use your old config files with SaraSortd.py. - - ## Usage SaraSortd is for people who don't want to manually sort files, people who want to organise files, and people who want an automatic naming standard for their files. @@ -24,7 +17,6 @@ Example use-cases: - Regularly cloning important files into a backup directory. - ## Dependencies python @@ -51,12 +43,12 @@ Here's a step-by-step tutorial (in case you don't want to watch the video). ## Config explanation -### SaraSortd Config (Config.toml) +### SaraSortd Config (GlobalConf.toml) ``` -Title = "SaraSortd Config" # NOTE: Do not change the title. +Title = "SaraSortd Config" # NOTE: Do not change the title. This is so that the program knows which config file is which. -Version = "4.0" # Just the version number for the config file. +Version = "5.1" # 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. @@ -68,10 +60,10 @@ DotFiles = 0 # If SaraSortd should sort files that begin with ".". This is mainl Logging = 1 # If SaraSortd's logging system should be active. If this is 0, nothing will be logged into files. -OverwriteDirConf = 0 # If SaraSortd should overwrite directory configs with DirConfig.toml. 0 is no, 1 is yes. +OverwriteDirConf = 0 # If SaraSortd should overwrite directory configs with the config templates. 0 is no, 1 is yes. [Variables] # Only use these in config files, not the actual file names themselves. -NextNum = "*" # The next available number. If 1 already exists, 2 will be used. Starts at 1. +NextNum = "*" # The next available number. If 1 already exists, 2 will be used. NextChar = "&" # The next available character. If A already exists, B will be used. @@ -139,18 +131,18 @@ Unset = "Error: %% is not set." # When a value isn't set. ``` -### Output Directory Config (DirConfig.toml) +### Output Directory Config (OutputDirConf.toml) -The output directory config references the SaraSortd config (Config.toml). This means that you can, for example, use the character assigned to "NextNum" in Config.toml in this config (DirConfig.toml). This applies to all Variables in the SaraSortd config (Config.toml). +The output directory config references the SaraSortd config (GlobalConf.toml). This means that you can, for example, use the character assigned to "NextNum" in GlobalConf.toml in this config (OutputDirConf.toml). This applies to all Variables in the SaraSortd config (GlobalConf.toml). ``` -Title = "Unset" # The title of the config. This currently does nothing for SaraSortd, so it can be anything. It gets automatically updated when DirConfig.toml gets copied to an output directory. +Title = "Unset" # NOTE: Do not change the title. This is so that the program knows which config file is which. -Version = "4.0" # The version number of the config. +Version = "5.1" # 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. -ParentDir = "Unset" # The name of this directory. It gets automatically updated when DirConfig.toml gets copied to an output directory. +ParentDir = "Unset" # The name of this directory. It gets automatically updated when this config gets copied to an output directory. ValidInputDirs = ["*"] # Directories that are valid for sorting. Basically, if a file is from one of these directories, they can be sorted here. * is a wildcard; ? is a one-character wilcard. E.G: if "ValidInputDirs = ["/TestDir/*"]" any file from any directory in "/TestDir" will be allowed to be sorted here. @@ -180,11 +172,21 @@ Pattern = "*" # A pattern used to sort files to this directory. * is a wildcard; NewFileName = "~^" # A pattern for the new names of the files that get sorted to this directory from matching this "Pattern". -NextNum = 1 # Used to keep track of the next available number for file names. If you have two of the character that represents NextNum (Found in Config.toml), you can stack them together to make 01 or 001 instead of 1. It gets automatically incremented when NextNum is used in NewFileName, and a file gets sorted to this directory and renamed. +NextNum = 1 # Used to keep track of the next available number for file names. If you change NextNum to be 01 or 001 instead of 1, it'll still work. 09 => 10. It gets automatically incremented when NextNum is used in NewFileName, and a file gets sorted to this directory and renamed. -NextChar = "A" # Used to keep track of the next available letter for file names. It gets automatically incremented (E.G: A into B or AA into AB then AZ into BA) when NextChar is used in NewFileName, and a file gets sorted to this directory and renamed. +NextChar = "A" # Used to keep track of the next available letter for file names. If you change NextChar to be AA or AAA instead of A, it'll still work. AZ => BA. It gets automatically incremented (E.G: A into B or AA into AB then AZ into BA) when NextChar is used in NewFileName, and a file gets sorted to this directory and renamed. CaseSensitive = 0 # Whether this "Pattern" is case-sensitive or not. 1 is yes, 0 is no. E.G: if CaseSensitive = 1 and this "Pattern" is "*.PNG", a file named "picture.png" won't get sorted to this directory. If CaseSensitive = 0 and this "Pattern" is "*.PNG", a file named "picture.png" *will* get sorted to this directory. Overwrite = 1 # Whether this specific file type can be overwritten by others of the same type. 0 is no, 1 is yes. ``` + +### Input Directory Config (InputDirConf.toml) + +``` +Title = "Unset" # NOTE: Do not change the title. This is so that the program knows which config file is which. + +Version = "5.1" + +ParentDir = "Unset" # The name of this directory. It gets automatically updated when this config gets copied to an output directory. +``` diff --git a/Config.toml b/GlobalConf.toml similarity index 92% rename from Config.toml rename to GlobalConf.toml index 38374af..c0c094c 100644 --- a/Config.toml +++ b/GlobalConf.toml @@ -1,5 +1,5 @@ Title = "SaraSortd Config" -Version = "4.0" +Version = "5.1" SafeMode = 1 SilentMode = 0 CheckInput = 5 @@ -30,7 +30,8 @@ FailedDir = "%RootDir%/.Failed" [Names] LogFileName = "[y].[m].[d]" -DirConfName = ".@Config" +InDirConfName = ".@Config" +OutDirConfName = ".@Config" FileHistoryName = ".@History" [Log] diff --git a/InputDirConf.toml b/InputDirConf.toml new file mode 100644 index 0000000..6def304 --- /dev/null +++ b/InputDirConf.toml @@ -0,0 +1,3 @@ +Title = "Unset" +Version = "5.1" +ParentDir = "Unset" diff --git a/DirConfig.toml b/OutputDirConf.toml similarity index 86% rename from DirConfig.toml rename to OutputDirConf.toml index 5ec450d..3afb550 100644 --- a/DirConfig.toml +++ b/OutputDirConf.toml @@ -1,5 +1,5 @@ Title = "Unset" -Version = "4.0" +Version = "5.1" LastFile = "Unset" ParentDir = "Unset" ValidInputDirs = ["*"] @@ -9,7 +9,7 @@ DeleteOrg = 1 [[Files]] Pattern = "*" NewFileName = "~^" -NextNum = 1 +NextNum = "1" NextChar = "A" CaseSensitive = 0 Overwrite = 1 diff --git a/SaraSortd.py b/SaraSortd.py index 435dda5..c342a92 100644 --- a/SaraSortd.py +++ b/SaraSortd.py @@ -6,9 +6,9 @@ import shutil import time import toml -# Version 4.0 +# Version = "5.1" -ConfPath = "./Config.toml" +ConfPath = "./GlobalConf.toml" Conf = None ConfVars = None @@ -222,18 +222,18 @@ def Dir(Path, Output = True, CopyConf = True): os.makedirs(Path, exist_ok=True) if CopyConf: - NewDirConf = f"{Parse(String = ConfNames['DirConfName'], Path = ConfPath, Parent = ParentName)}.toml" + 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}/{NewDirConf}") + os.path.join(f"{Path}/{NewOutDirConf}") ): - Clone("DirConfig.toml", Path, NewDirConf) + Clone("OutputDirConf.toml", Path, NewOutDirConf) UpdateConf( - f"{Path}/{Parse(String = ConfNames['DirConfName'], Path = ConfPath, Parent = ParentName)}.toml", + f"{Path}/{Parse(String = ConfNames['OutDirConfName'], Path = ConfPath, Parent = ParentName)}.toml", "ParentDir", ParentName, ) UpdateConf( - f"{Path}/{Parse(String = ConfNames['DirConfName'], Path = ConfPath, Parent = ParentName)}.toml", + f"{Path}/{Parse(String = ConfNames['OutDirConfName'], Path = ConfPath, Parent = ParentName)}.toml", "Title", f"{ParentName} Config", ) @@ -266,13 +266,13 @@ def DecideNewPath(FilePath): ParentName = os.path.basename(Output) - DirConfName = Parse(String = ConfNames["DirConfName"], Path = ConfPath, Parent = ParentName) - DirConfPath = f"{Output}/{DirConfName}.toml" + OutDirConfName = Parse(String = ConfNames["OutDirConfName"], Path = ConfPath, Parent = ParentName) + OutDirConfPath = f"{Output}/{OutDirConfName}.toml" - ValidInputDirs = GetConf("ValidInputDirs", DirConfPath) + ValidInputDirs = GetConf("ValidInputDirs", OutDirConfPath) for ValidInputDir in ValidInputDirs: - ValidInputDir = Parse(String = ValidInputDir, Parent = GetConf("ParentDir", DirConfPath)) + ValidInputDir = Parse(String = ValidInputDir, Parent = GetConf("ParentDir", OutDirConfPath)) TextOutput = Parse(String = ConfLog["MatchPattern"], VarCall = f"{os.path.dirname(FilePath)} against {ValidInputDir}") LogWrite(TextOutput) @@ -282,12 +282,12 @@ def DecideNewPath(FilePath): if (InputDirValid): break - if not os.path.exists(DirConfPath) or not InputDirValid: + if not os.path.exists(OutDirConfPath) or not InputDirValid: continue OutputFiles = 0 - FileLimitConf = GetConf("FileLimit", DirConfPath) + FileLimitConf = GetConf("FileLimit", OutDirConfPath) if FileLimitConf > 0: for OutputFile in os.listdir(Output): @@ -299,7 +299,7 @@ def DecideNewPath(FilePath): if OutputFiles >= FileLimitConf: continue - FileConf = GetConf("Files", DirConfPath) + FileConf = GetConf("Files", OutDirConfPath) if not FileConf: continue @@ -320,25 +320,26 @@ def DecideNewPath(FilePath): if Match: NewFileName = File["NewFileName"] - NewFileName = Parse(String = NewFileName, Path = DirConfPath, OrgFile = UnsortedFile, NextNum = File["NextNum"], NextChar = File["NextChar"], Parent = ParentName) + NewFileName = Parse(String = NewFileName, Path = OutDirConfPath, OrgFile = UnsortedFile, NextNum = File["NextNum"], NextChar = File["NextChar"], Parent = ParentName) if File["Overwrite"] == 0 and os.path.exists(os.path.join(Output, NewFileName)): continue if ConfVars["NextNum"] in File["NewFileName"]: - ConfData = toml.load(DirConfPath) - - NewNum = (int(File["NextNum"]) + 1) + ConfData = toml.load(OutDirConfPath) + Width = len(File["NextNum"]) + NewNum = str((int(File["NextNum"]) + 1)).rjust(Width, "0") + print(File["NextNum"],"=>",NewNum) for Item in ConfData.get("Files", []): if Item.get("Pattern") == File["Pattern"]: Item["NextNum"] = NewNum break - with open(DirConfPath, "w", encoding="utf-8") as ConfFile: + with open(OutDirConfPath, "w", encoding="utf-8") as ConfFile: toml.dump(ConfData, ConfFile) - TextOutput = Parse(String = ConfLog["ValueSet"], VarCall = f"NextChar to {NewNum}") + TextOutput = Parse(String = ConfLog["ValueSet"], VarCall = f"NextNum to {NewNum}") LogWrite(TextOutput) Speak(TextOutput) @@ -363,14 +364,14 @@ def DecideNewPath(FilePath): NewChar = "".join(Result) - ConfData = toml.load(DirConfPath) + ConfData = toml.load(OutDirConfPath) for Item in ConfData.get("Files", []): if Item.get("Pattern") == File["Pattern"]: Item["NextChar"] = NewChar break - with open(DirConfPath, "w", encoding="utf-8") as ConfFile: + with open(OutDirConfPath, "w", encoding="utf-8") as ConfFile: toml.dump(ConfData, ConfFile) TextOutput = Parse(String = ConfLog["ValueSet"], VarCall = f"NextChar to {NewChar}") @@ -396,7 +397,7 @@ def Sort(FilePath): NewDirPath = os.path.dirname(NewPath) NewName = os.path.basename(NewPath) - if (GetConf("DeleteOrg", f"{NewDirPath}/{Parse(String = ConfNames['DirConfName'], Parent = (os.path.basename(NewDirPath)))}.toml") == 1): + if (GetConf("DeleteOrg", f"{NewDirPath}/{Parse(String = ConfNames['OutDirConfName'], Parent = (os.path.basename(NewDirPath)))}.toml") == 1): Delete = True else: @@ -404,7 +405,7 @@ def Sort(FilePath): try: Clone(FilePath, NewDirPath, NewName, Delete) - UpdateConf(f"{NewDirPath}/{Parse(String = ConfNames['DirConfName'], Parent = os.path.basename(NewDirPath))}.toml", "LastFile", NewName) + UpdateConf(f"{NewDirPath}/{Parse(String = ConfNames['OutDirConfName'], Parent = os.path.basename(NewDirPath))}.toml", "LastFile", NewName) TextOutput = Parse(String = ConfLog["Sorted"], VarCall = f"{FilePath} to {NewDirPath}/{NewName}") LogWrite(TextOutput) @@ -437,8 +438,8 @@ def Init(): Output = Parse(String = Output, Parent = os.path.basename(os.path.dirname(Output))) Dir(Output) - DirConfPath = f"{Output}/{Parse(String = ConfNames["DirConfName"], Parent = os.path.basename(Output))}.toml" - ConfData = toml.load(DirConfPath) + OutDirConfPath = f"{Output}/{Parse(String = ConfNames["OutDirConfName"], Parent = os.path.basename(Output))}.toml" + ConfData = toml.load(OutDirConfPath) for Item in ConfData.get("Files", []): Character = re.escape(ConfVars["NextChar"]) @@ -448,7 +449,7 @@ def Init(): if Width > 0: Item["NextChar"] = Item["NextChar"].upper().rjust(Width, "A") - with open(DirConfPath, "w", encoding = "utf-8") as ConfFile: + with open(OutDirConfPath, "w", encoding = "utf-8") as ConfFile: toml.dump(ConfData, ConfFile) TextOutput = Parse(String = ConfLog["Start"], Path = ConfPath) @@ -462,7 +463,7 @@ def Init(): Speak(TextOutput) else: - print("NO CONFIG FOUND! Make sure the 'Config.toml' is in the same directory as 'SaraSortd.py'") + print("NO CONFIG FOUND! Make sure the 'GlobalConf.toml' is in the same directory as 'SaraSortd.py'") def Main(): @@ -510,5 +511,4 @@ def Main(): LogWrite(TextOutput) Speak(TextOutput) - Init()