Have you ever wanted to find out how much room a particular directory was taking up on your hard drive? A roommate of mine in college was having trouble keeping track of where his hard drive space is going, so the following program provided a solution that allows a brief overview of a directory's size along with all of its children. A tree view is printed out in ASCII characters showing the relationship of each directory along with its size in a format easily readable to humans. The output can always be redirected to a text file if it needs to be saved for viewing later on.
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 | import os, sys
################################################################################
def main():
try:
tree = SizeTree(os.path.abspath(sys.argv[1]))
except IndexError:
print('Usage: {} <directory>'.format(os.path.basename(sys.argv[0])))
else:
show(tree)
def show(tree):
print('{} [{}]'.format(tree.path, convert(tree.total_size)))
walk(tree, '')
if not tree.children:
print('No subfolders exist')
def walk(tree, prefix):
dir_prefix, walk_prefix = prefix + '+---', prefix + '| '
for pos, neg, child in enumerate2(tree.children):
if neg == -1:
dir_prefix, walk_prefix = prefix + '\\---', prefix + ' '
print('{}{} [{}]'.format(dir_prefix, child.name,
convert(child.total_size)))
walk(child, walk_prefix)
def enumerate2(sequence):
length = len(sequence)
for count, value in enumerate(sequence):
yield count, count - length, value
################################################################################
class SizeTree:
def __init__(self, path, name=None):
self.path = path
self.name = os.path.basename(path) if name is None else name
self.children = []
self.file_size = 0
self.total_size = 0
try:
dir_list = os.listdir(path)
except OSError:
pass
else:
for name in dir_list:
path_name = os.path.join(path, name)
if os.path.isdir(path_name):
size_tree = SizeTree(path_name, name)
self.children.append(size_tree)
self.total_size += size_tree.total_size
elif os.path.isfile(path_name):
try:
self.file_size += os.path.getsize(path_name)
except OSError:
pass
self.total_size += self.file_size
################################################################################
def convert(number):
"Convert bytes into human-readable representation."
if not number:
return '0 Bytes'
assert 0 < number < 1 << 110, 'number out of range'
ordered = reversed(tuple(format_bytes(partition_number(number, 1 << 10))))
cleaned = ', '.join(item for item in ordered if item[0] != '0')
return cleaned
def partition_number(number, base):
"Continually divide number by base until zero."
div, mod = divmod(number, base)
yield mod
while div:
div, mod = divmod(div, base)
yield mod
def format_bytes(parts):
"Format partitioned bytes into human-readable strings."
for power, number in enumerate(parts):
yield '{} {}'.format(number, format_suffix(power, number))
def format_suffix(power, number):
"Compute the suffix for a certain power of bytes."
return (PREFIX[power] + 'byte').capitalize() + ('s' if number != 1 else '')
PREFIX = ' kilo mega giga tera peta exa zetta yotta bronto geop'.split(' ')
################################################################################
if __name__ == '__main__':
main()
|
This simple utility was re-envisioned with a GUI that has been substantially enhanced and is available as recipe 577567.
For python 2.6 you will have to rewrite the print commands(e.g.: line: 14 print('{} [{}]'.format(tree.path, convert(tree.total_size))) to print('{0} [{1}]'.format(tree.path, convert(tree.total_size))))
Otherwise python would not know where to put the arguments.
Since I cannot copy the entire program as a comment(max. 3000 chars.), I will put the affected lines here: