Created
November 23, 2023 06:48
-
-
Save edavis/2296f999314bda09b79b1f5ca7e44ed6 to your computer and use it in GitHub Desktop.
Parse a directory of torrent files and return the total size of all files within
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import os, glob | |
from io import BytesIO | |
class End(Exception): pass | |
def decode(stream): | |
delim = stream.read(1) | |
if delim == b'd': | |
values = {} | |
while True: | |
try: | |
key = decode(stream) | |
val = decode(stream) | |
values.update({key: val}) | |
except End: | |
break | |
return values | |
elif delim == b'l': | |
values = [] | |
while True: | |
try: | |
val = decode(stream) | |
values.append(val) | |
except End: | |
break | |
return values | |
elif delim == b'i': | |
t = '' | |
while True: | |
d = stream.read(1) | |
if d == b'e': | |
break | |
t += d.decode() | |
return int(t, 10) | |
elif delim == b'e': | |
raise End | |
else: # byte string | |
t = delim.decode() | |
while True: | |
d = stream.read(1) | |
if d == b':': | |
break | |
t += d.decode() | |
return stream.read(int(t, 10)) | |
def human_readable(size, suffix='B'): | |
fmt = '{:3.1f}{}{}' | |
units = ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi'] | |
for unit in units: | |
if abs(size) < 1024.0: | |
return fmt.format(size, unit, suffix) | |
size /= 1024.0 | |
return fmt.format(size, 'Yi', suffix) | |
def main(): | |
import argparse | |
parser = argparse.ArgumentParser() | |
parser.add_argument('input') | |
args = parser.parse_args() | |
if os.path.isdir(args.input): | |
torrents = glob.glob(args.input + '/*.torrent') | |
else: | |
torrents = [args.input] | |
total_bytes = 0 | |
for torrent in torrents: | |
with open(torrent, 'rb') as fp: | |
stream = BytesIO(fp.read()) | |
parsed = decode(stream) | |
info = parsed.get(b'info', {}) | |
if b'files' in info: # multi | |
for fname in info[b'files']: | |
# print(fname[b'path'], fname[b'length']) | |
total_bytes += fname[b'length'] | |
elif b'length' in info: # single | |
# print(info[b'name'], info[b'length']) | |
total_bytes += info[b'length'] | |
else: | |
print("could not find either 'files' or 'length' key in info dict") | |
print(human_readable(total_bytes)) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment