`tree' script (`du'-like) revisited

François Pinard pinard at iro.umontreal.ca
Wed Mar 8 01:50:48 CET 2000


Hi, people.  Here is a small revision of my little `tree' script (as you
see, nothing big in there :-).  I added a `-b' option for showing the
biggest directories first.  The default is using lexicographical order.
Of course, if you find bugs or improve it, please tell me.  Keep happy!

-------------- next part --------------
#!/usr/bin/python
# Produce directory hierarchy with sizes, well sorted and indented.
# Copyright ? 1996, 1999, 2000 Progiciels Bourbeau-Pinard inc.
# Fran?ois Pinard <pinard at iro.umontreal.ca>, 1996.

# Idea from Pierre Rioux <riouxp at 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:]))
-------------- next part --------------

-- 
Fran?ois Pinard   http://www.iro.umontreal.ca/~pinard


More information about the Python-list mailing list