Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a314614055 | ||
|
|
3aa28f76cf | ||
|
|
89f4e59041 | ||
|
|
dc60a9828e | ||
|
|
4901d346f2 | ||
|
|
b04c3426a7 | ||
|
|
15ced89964 | ||
|
|
475eda8dd2 | ||
|
|
e9974f90ee | ||
|
|
68e33861a9 | ||
|
|
f0b2ec62ef |
No files matched your search
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 366 KiB |
|
After Width: | Height: | Size: 914 B |
@@ -1,11 +1,17 @@
|
||||
# SaraSortd
|
||||
(Version = "5.1")
|
||||
<img align="center" src="Banners/Main.png" width="100%" alt="SaraSortd: a file and directory sorting daemon built with python."/>
|
||||
|
||||
---
|
||||
|
||||
(Version = "6.2")
|
||||
|
||||
A python daemon that can automatically sort your files to your liking without using AI.
|
||||
|
||||
It's made by Sarah, hence the name. :3
|
||||
|
||||
## Usage
|
||||
If the first number in the version goes up, it means that old config files will not work with the new SaraSortd.py.
|
||||
|
||||
If the second number in the version goes up, something new got added, but your old config files will still work just fine.
|
||||
|
||||
<img align="center" src="Banners/Usage.png" width="100%" alt="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.
|
||||
|
||||
@@ -17,19 +23,14 @@ Example use-cases:
|
||||
|
||||
- Regularly cloning important files into a backup directory.
|
||||
|
||||
## Dependencies
|
||||
<img align="center" src="Banners/Dependencies.png" width="100%" alt="Dependencies"/>
|
||||
|
||||
python
|
||||
|
||||
toml: Use ```pip install toml``` to install toml.
|
||||
|
||||
## Versioning
|
||||
|
||||
If the first number in the version goes up, it means that old config files will not work with the new SaraSortd.py.
|
||||
|
||||
If the second number in the version goes up, something new got added, but your old config files will still work just fine.
|
||||
|
||||
## Installation
|
||||
<img align="center" src="Banners/Installation.png" width="100%" alt="Installation"/>
|
||||
|
||||
Here's an [installation video](https://youtu.be/ZMIaOhZA0kE).
|
||||
Here's a step-by-step tutorial (in case you don't want to watch the video).
|
||||
@@ -41,14 +42,14 @@ Here's a step-by-step tutorial (in case you don't want to watch the video).
|
||||
5. Run ```python SaraSortd.py``` to run the program. (This will make new directories for you.)
|
||||
6. Edit your output directories' configs.
|
||||
|
||||
## Config explanation
|
||||
<img align="center" src="Banners/ConfigInfo.png" width="100%" alt="Config Info"/>
|
||||
|
||||
### SaraSortd Config (GlobalConf.toml)
|
||||
<img align="center" src="Banners/GlobalConf.png" width="100%" alt="GlobalConf"/>
|
||||
|
||||
```
|
||||
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.2" # 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,17 +129,26 @@ 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".
|
||||
```
|
||||
|
||||
|
||||
### Output Directory Config (OutputDirConf.toml)
|
||||
<img align="center" src="Banners/OutputDirConf.png" width="100%" alt="OutputDirConf"/>
|
||||
|
||||
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" # 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.2" # 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.
|
||||
|
||||
@@ -181,12 +191,20 @@ CaseSensitive = 0 # Whether this "Pattern" is case-sensitive or not. 1 is yes, 0
|
||||
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)
|
||||
<img align="center" src="Banners/InputDirConf.png" width="100%" alt="InputDirConf"/>
|
||||
|
||||
```
|
||||
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.2"
|
||||
|
||||
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.
|
||||
```
|
||||
@@ -1,5 +1,5 @@
|
||||
Title = "SaraSortd Config"
|
||||
Version = "5.1"
|
||||
Version = "6.2"
|
||||
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 %%."
|
||||
@@ -1,3 +1,8 @@
|
||||
Title = "Unset"
|
||||
Version = "5.1"
|
||||
Version = "6.2"
|
||||
ParentDir = "Unset"
|
||||
SortDirs = 0
|
||||
|
||||
[[Files]]
|
||||
Pattern = "*"
|
||||
CaseSensitive = 0
|
||||
@@ -1,5 +1,5 @@
|
||||
Title = "Unset"
|
||||
Version = "5.1"
|
||||
Version = "6.2"
|
||||
LastFile = "Unset"
|
||||
ParentDir = "Unset"
|
||||
ValidInputDirs = ["*"]
|
||||
|
||||
@@ -6,7 +6,7 @@ import shutil
|
||||
import time
|
||||
import toml
|
||||
|
||||
# Version = "5.1"
|
||||
# Version = "6.2"
|
||||
|
||||
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)
|
||||
|
||||