-
Notifications
You must be signed in to change notification settings - Fork 0
/
rtorrent-cleanup.py
138 lines (119 loc) · 5.81 KB
/
rtorrent-cleanup.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
134
135
136
137
138
#!/usr/bin/python
from __future__ import print_function
import os
import shutil
import bencode
import argparse
args = object()
def check_if_single_file_torrent(torrent_file_path):
#return (path in download_dirs) # old version
# new version
with open (torrent_file_path, "r") as f:
content = f.read()
decoded_content = bencode.decode(content)
result = not ("files" in decoded_content["info"])
return result
def get_dir_or_file_size(path):
result = 0
if os.path.isdir(path):
total_size = 0
for dirpath, dirnames, filenames in os.walk(path):
for f in filenames:
fp = os.path.join(dirpath, f)
total_size += os.path.getsize(fp)
result = total_size
elif os.path.isfile(path):
result = os.path.getsize(path)
return result
def delete_path(path):
debug("deleting " + path)
if os.path.isdir(path):
shutil.rmtree(path)
elif os.path.isfile(path):
os.remove(path)
def format_size(size):
if size >= 1024**3: # GB
return str(size/(1024**3)) + "GB"
if size >= 1024**2: # MB
return str(size/(1024**2)) + "MB"
if size >= 1024**1: # KB
return str(size/(1024**1)) + "KB"
return str(size) + "B"
def debug(msg):
if args.debug_flag:
print(msg)
if args.pause_on_debug:
print("Continue? ", end = "")
raw_input()
def main():
# parse arguments
# TODO option to also look into the folders and delete unreferenced files there
# TODO option to confirm every deletion
# TODO quite option to just run without any confirmations
# TODO option for save mode that just moves all unreferenced files into a target directory
parser = argparse.ArgumentParser(description='Deletes files from rtorrent download directories that are not referenced in rtorrent', epilog='Github: github.com/ntv1000')
parser.add_argument('--debug', dest='debug_flag', action='store_true', default=False, help='Debugging information will be displayed')
parser.add_argument('--pause_on_debug', dest='pause_on_debug', action='store_true', default=False, help='Debugging information will be displayed')
parser.add_argument('--dry', dest='dryrun_flag', action='store_true', default=False, help='All files that would be deleted will be listed, but not deleted')
parser.add_argument('rtorrent_working_dir', metavar='WORKING_DIR', help='The working directory of your rtorrent instance')
parser.add_argument('rtorrent_download_dirs', metavar='DOWNLOAD_DIR', nargs='+', help='The download directories that should be cleaned up')
global args
args = parser.parse_args()
debug('debug_flag=' + str(args.debug_flag))
debug('dryrun_flag=' + str(args.dryrun_flag))
debug('rtorrent_working_dir=' + args.rtorrent_working_dir)
debug('rtorrent_download_dirs=' + str(args.rtorrent_download_dirs))
rtorrent_files = [os.path.join(args.rtorrent_working_dir, f) for f in os.listdir(args.rtorrent_working_dir) if os.path.isfile(os.path.join(args.rtorrent_working_dir, f)) and os.path.splitext(f)[1] == ".rtorrent"]
downloads = list()
referenced = list()
for dir in args.rtorrent_download_dirs:
downloads += [os.path.join(dir, x) for x in os.listdir(dir)]
print("found " + str(len(downloads)) + " downloaded files")
print("found " + str(len(rtorrent_files)) + " rtorrent files")
for rtorrent_file in rtorrent_files:
#debug("rtorrent_file: " + rtorrent_file)
content = ""
with open (rtorrent_file, "r") as f:
content = f.read()
if content != "":
path = bencode.decode(content)["directory"]
# extrect the path to the tied torrent file (not really tied, rather the torrent file with the same name)
torrent_file = os.path.splitext(rtorrent_file)[0]
if os.path.exists(torrent_file):
if check_if_single_file_torrent(torrent_file):
# for "single-file"-torrent the filename has to be taken from the tied torrent_file
with open (torrent_file, "r") as f:
content = f.read()
single_file_name = bencode.decode(content)["info"]["name"]
assert os.path.isfile(os.path.join(path, single_file_name))
debug("single-file torrent: " + single_file_name)
referenced.append(os.path.join(path, single_file_name))
else:
debug("multi-file torrent: " + path)
referenced.append(path)
else:
print("ERROR - missing torrent file: '" + torrent_file + "' for rtorrent file '" + rtorrent_file + "'")
else:
print("ERROR - empty file")
print("found " + str(len([x for x in referenced])) + " files that were referenced")
print("found " + str(len(set(downloads) - set(referenced))) + " files that were not referenced")
not_referenced = list(set(downloads) - set(referenced))
#not_referenced = [x for x in downloads if x not in referenced]
if len(not_referenced) > 0:
sizes = [get_dir_or_file_size(x) for x in not_referenced]
total_size = sum(sizes)
print ("deleting all unreferenced files will free up " + format_size(total_size) + " of storage")
if args.dryrun_flag:
print("Not referenced files:")
for path in not_referenced:
print(path)
else:
print("unreferenced files will now be deleted (WARNING: DELETED FILES ARE NOT RECOVERABLE) continue? (yes/no) ",end="")
input = raw_input()
if input == "yes":
for path in not_referenced:
delete_path(path)
else:
print("there are no files that are not referenced in rtorrent - exiting...")
if __name__ == "__main__":
main()