Rewrite mkpodcastplaylist for python3 and cleanup
parent
dd21860151
commit
f967107009
@ -1,109 +1,119 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
"""
|
|
||||||
This is a program that generates playlists based on the size of the
|
from functools import partial
|
||||||
largest file/directory. It searches directories, getting their size
|
from pathlib import Path
|
||||||
and lists the first file in the largest direcotry.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import errno
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
class File:
|
def ensure_path(p):
|
||||||
"""A file has a size and a name"""
|
return p if isinstance(p, Path) else Path(p)
|
||||||
|
|
||||||
|
def include_all(*args):
|
||||||
|
return True
|
||||||
|
|
||||||
|
class File:
|
||||||
def __init__(self, path):
|
def __init__(self, path):
|
||||||
self.name = path
|
self.path = ensure_path(path)
|
||||||
self.size = os.path.getsize(self.name)
|
self.stat = os.stat(self.path)
|
||||||
|
|
||||||
def get_size(self):
|
@property
|
||||||
"""Get the size of the current file"""
|
def name(self):
|
||||||
return self.size
|
return self.path.name
|
||||||
|
|
||||||
def get_name(self):
|
def size(self):
|
||||||
"""Get the name of the current file"""
|
return self.stat.st_size
|
||||||
return self.name
|
|
||||||
|
|
||||||
class Directory:
|
def get(values, *, existing=set()):
|
||||||
"""A directory is a list that can contain files and other directories."""
|
for val in values:
|
||||||
|
if val in existing:
|
||||||
|
continue
|
||||||
|
if val.size() == 0:
|
||||||
|
continue
|
||||||
|
yield val
|
||||||
|
|
||||||
def __init__(self, path):
|
def by_size(x, *, filter=None):
|
||||||
self.path = path
|
return x.size(filter=filter)
|
||||||
self.files = []
|
|
||||||
|
def by_name(x):
|
||||||
files = os.listdir(path)
|
return x.name
|
||||||
files.sort()
|
|
||||||
for fil in files:
|
class Directory:
|
||||||
if type(fil).__name__ == "str":
|
def __init__(self, base_dir):
|
||||||
self.files.append(File("%s/%s" % (path, fil)))
|
self.base = ensure_path(base_dir)
|
||||||
|
self.files = {}
|
||||||
def get_dir_name(self):
|
self.dirs = {}
|
||||||
"""Get the name of the current directory."""
|
|
||||||
return self.path
|
@property
|
||||||
|
def name(self):
|
||||||
def get_dir_size(self):
|
return self.base
|
||||||
"""Get the size of the current directory."""
|
|
||||||
ret = 0
|
def list_by_size(self, *, files=None):
|
||||||
for fil in self.files:
|
files = set() if files is None else files
|
||||||
ret += fil.get_size()
|
|
||||||
return ret
|
while True:
|
||||||
|
dirs = get(self.dirs.values(), existing=files)
|
||||||
def get_head_file(self):
|
without_file = lambda x: x not in files
|
||||||
"""Get the 'head' file in the directory."""
|
filtered_by_size = partial(by_size, filter=without_file)
|
||||||
return self.files[0].get_name()
|
dirs_by_size = sorted(dirs, key=filtered_by_size, reverse=True)
|
||||||
|
if len(dirs_by_size):
|
||||||
def num_files(self):
|
largest_dir = dirs_by_size[0]
|
||||||
"""Get the number of files in the directory."""
|
current_file = next(largest_dir.list_by_size(files=files))
|
||||||
return len(self.files)
|
files.add(current_file)
|
||||||
|
yield current_file
|
||||||
def remove_head_file(self):
|
continue
|
||||||
"""Remove the head file from being counted."""
|
|
||||||
self.files = self.files[1:]
|
files_by_name = sorted(get(self.files.values(), existing=files),
|
||||||
|
key=by_name)
|
||||||
def sort_dir(direct):
|
if len(files_by_name):
|
||||||
"""Sort the directories by size."""
|
current_file = files_by_name[0]
|
||||||
return direct.get_dir_size()
|
files.add(current_file)
|
||||||
|
yield current_file
|
||||||
def main():
|
continue
|
||||||
"""The main script."""
|
|
||||||
try:
|
|
||||||
base_dir = sys.argv[1]
|
|
||||||
except IndexError:
|
|
||||||
print "Must enter path of directory to search. Example: %s ./foo" % \
|
|
||||||
sys.argv[0]
|
|
||||||
os.abort()
|
|
||||||
|
|
||||||
if os.path.exists(base_dir) == False:
|
|
||||||
print "Could not find path: '%s'" % base_dir
|
|
||||||
os.abort()
|
|
||||||
|
|
||||||
if base_dir[-1] == "/":
|
|
||||||
base_dir = base_dir[:-1]
|
|
||||||
|
|
||||||
base_dir_listing = os.listdir(base_dir)
|
|
||||||
directories = []
|
|
||||||
|
|
||||||
for direct in base_dir_listing:
|
|
||||||
rel_dir = "%s/%s" % (base_dir, direct)
|
|
||||||
|
|
||||||
if os.path.islink(rel_dir) == False and os.path.isdir(rel_dir):
|
|
||||||
directories.append(Directory(rel_dir))
|
|
||||||
|
|
||||||
while directories:
|
|
||||||
directories.sort(key=sort_dir)
|
|
||||||
directories.reverse()
|
|
||||||
headfile = directories[0].get_head_file()
|
|
||||||
#headfile = headfile.replace('podcasts/', 'podcast/', 1)
|
|
||||||
#print headfile
|
|
||||||
try:
|
|
||||||
sys.stdout.write("%s\n" % headfile)
|
|
||||||
except IOError as e:
|
|
||||||
if e.errno == errno.EPIPE:
|
|
||||||
return
|
return
|
||||||
raise e
|
|
||||||
directories[0].remove_head_file()
|
|
||||||
if directories[0].num_files() == 0:
|
|
||||||
directories = directories[1:]
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
def size(self, *, filter=None):
|
||||||
main()
|
filter = include_all if filter is None else filter
|
||||||
|
|
||||||
|
total = 0
|
||||||
|
for node in self.files.values():
|
||||||
|
if filter(node):
|
||||||
|
total += node.size()
|
||||||
|
|
||||||
|
for node in self.dirs.values():
|
||||||
|
total += node.size(filter=filter)
|
||||||
|
|
||||||
|
return total
|
||||||
|
|
||||||
|
def directory(self, *parts):
|
||||||
|
if len(parts) == 0:
|
||||||
|
return self
|
||||||
|
|
||||||
|
part, *rest = parts
|
||||||
|
node = self.dirs.get(part)
|
||||||
|
if node is None:
|
||||||
|
node = Directory(part)
|
||||||
|
self.dirs[part] = node
|
||||||
|
|
||||||
|
return node.directory(*rest)
|
||||||
|
|
||||||
|
def add_file(self, path):
|
||||||
|
node = self.directory(*path.parent.parts)
|
||||||
|
node.files[path.name] = File(path)
|
||||||
|
return node.files[path.name]
|
||||||
|
|
||||||
|
def main(base_dir):
|
||||||
|
tree = Directory(base_dir)
|
||||||
|
for root, dirs, files in os.walk(base_dir):
|
||||||
|
for f in files:
|
||||||
|
tree.add_file(Path(root) / f)
|
||||||
|
|
||||||
|
for f in tree.list_by_size():
|
||||||
|
print("{}/{}".format(base_dir, f.path))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
from argparse import ArgumentParser
|
||||||
|
parser = ArgumentParser()
|
||||||
|
parser.add_argument('-o', '--output', default='.')
|
||||||
|
parser.add_argument('-d', '--directory', default=Path('.'), type=Path)
|
||||||
|
args = parser.parse_args()
|
||||||
|
main(args.directory)
|
||||||
|
Loading…
Reference in New Issue