Entry
'du' in Python
Jul 5th, 2000 10:03
Nathan Wallace, Hans Nowak, Snippet 389, Fran‡ois Pinard
"""
Packages: operating_systems.generic;tools
"""
#!/usr/bin/python
# Produce directory hierarchy with sizes, well sorted and indented.
# Copyright © 1996, 1999, 2000 Progiciels Bourbeau-Pinard inc.
# François Pinard <pinard@iro.umontreal.ca>, 1996.
# Idea from Pierre Rioux <riouxp@bch.umontreal.ca>, 1996-07-12.
"""\
Usage: tree [OPTION]... [PATH]...
-b biggest directories first
-l LEVEL disregard directories more than LEVEL levels deep
-s SIZE disregard directories smaller than SIZE Kb
"""
import getopt, os, string, sys
def main(*arguments):
# Decode options.
biggest_option = level_option = size_option = None
options, arguments = getopt.getopt(arguments, 'bl:s:')
for option, value in options:
if option == '-b':
biggest_option = 1
elif option == '-l':
level_option = int(value)
elif option == '-s':
size_option = int(value)
# Get the data, properly filtered.
items = []
for line in os.popen('du %s' % string.join(arguments)).readlines():
text, path = string.split(line, '\t')
size = int(text)
if not size_option or size >= size_option:
split = string.split(path[:-1], '/')
if not level_option or len(split) <= level_option:
items.append((split, size))
# Sort the information as wanted.
if biggest_option:
value = {}
for split, size in items:
value[tuple(split)] = -size
items2 = []
for split, size in items:
pairs = []
for counter in range(len(split)):
pairs.append((value[tuple(split[:counter+1])], split[counter]))
items2.append(pairs)
items2.sort()
items = []
for pairs in items2:
split = map(lambda((size, fragment)): fragment, pairs)
size = -pairs[-1][0]
items.append((split, size))
else:
items.sort()
# Erase unneeded fragments of vertical lines.
clean(items)
items.reverse()
clean(items)
items.reverse()
# Erase leftmost white columns.
skip = 0
split, size = items[0]
while not split[skip]:
skip = skip + 1
# Produce display.
for split, size in items:
sys.stdout.write('%7d ' % size)
for item in split[skip:-1]:
if item:
sys.stdout.write('| ')
else:
sys.stdout.write(' ')
sys.stdout.write('\\_ %s\n' % split[-1])
def clean(items):
# The basename is always written. Intermediate directories
# normally print as `|', yet None is used to inhibit the line.
draw = []
for split, size in items:
while len(draw) > len(split) - 1:
del draw[-1]
while len(draw) < len(split) - 1:
draw.append(0)
draw.append(1)
for counter in range(len(split) - 1):
if not draw[counter]:
split[counter] = None
if __name__ == '__main__':
apply(main, tuple(sys.argv[1:]))