-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathworkfolder_cleaner.py
executable file
·133 lines (118 loc) · 4.24 KB
/
workfolder_cleaner.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import os
import shutil
import logging
import argparse
import datetime as dt
from pathlib import Path
from contextlib import suppress
def safe_directory_name(string: str):
"""Checks if a string can be used as a directory name"""
safe_characters = {'.', ',', '+', '-', '_', ' '}
for char in string:
if not char.isalnum() and char not in safe_characters:
return False
return True
def main():
desc = '''Workfolder & Desktop Cleaner\nArchives your desktop files to the
last day Workfolder, creates a new Workfolder and archives old workfolders
that exceed the cutoff limit.'''
parser = argparse.ArgumentParser(description=desc)
parser.add_argument(
"-workfolder",
help="Main Workfolder. One subdirectory will be created, in every run.",
required=True,
type=Path
)
parser.add_argument(
"-archive",
help="Archive directory name. Will be a subdirectory of Workfolder. "
"Defaults to ARCHIVE.",
default="ARCHIVE",
type=str
)
parser.add_argument(
"-clean_folders",
help="Directories that will be cleaned in each run. Contents will be moved to "
"daily workfolder.",
default=[],
nargs='*',
type=Path
)
parser.add_argument(
"-cutoff",
help="Cutoff limit in days. Any directory with modification date prior "
"to this will be moved to archive. "
"Defaults to 30 days.",
default=30,
type=int
)
parser.add_argument(
"-ds_fmt",
help="Date format for workfolder created directory. Defaults to: "
"'%%Y-%%m-%%d'",
default="%Y-%m-%d",
type=str
)
parser.add_argument(
"-rel_link",
help="Will create relative link for today in Workfolder path",
default=True,
type=bool
)
args = parser.parse_args()
cutoff_limit = args.cutoff
ds_fmt = args.ds_fmt
workfolder = args.workfolder.expanduser()
workfolder_archive = args.archive
if not safe_directory_name(workfolder_archive):
raise ValueError(f"Archive folder cannot be named {workfolder_archive!r}")
workfolder_archive = workfolder / args.archive
workfolder_today = workfolder / dt.date.today().strftime(ds_fmt)
link_workfolder_today = workfolder / 'today'
clean_folders = (folder.expanduser() for folder in args.clean_folders)
# configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# Archive old folders
workfolder_archive.mkdir(exist_ok=True, parents=True)
for folder in workfolder.iterdir():
if folder.is_symlink():
continue
modified_at = dt.datetime.fromtimestamp(os.path.getmtime(folder))
if (dt.date.today() - modified_at.date()).days > cutoff_limit:
folder.rename(workfolder_archive / folder.name)
logging.info("Archived %s to %s", folder, workfolder_archive)
# Delete empty folders
for folder in workfolder.iterdir():
if folder == workfolder_today or folder == workfolder_archive:
continue
with suppress(OSError):
folder.rmdir()
logging.info("Deleted empty folder: %s", folder)
# Create Dir for Today
workfolder_today.mkdir(exist_ok=True)
# Create home link
if args.rel_link:
with suppress(FileNotFoundError):
os.unlink(link_workfolder_today)
with suppress(OSError):
os.symlink(workfolder_today, link_workfolder_today)
logging.info("Created link: %s", link_workfolder_today)
# Clean Workfolder
for item in workfolder.glob("*"):
if item == link_workfolder_today or item == workfolder_archive:
continue
# If parse date, then should not move.
try:
dt.datetime.strptime(item.name, ds_fmt)
except ValueError:
pass
else:
continue
shutil.move(str(item), str(workfolder_today))
# Clean every other folder
for folder in clean_folders:
for item in folder.glob("*"):
shutil.move(str(item), str(workfolder_today))
logging.info("Cleaned %r", folder)
if __name__ == "__main__":
main()