指定したディレクトリ以下のファイルすべてに関数を適用する

ちょっとしたことから指定したディレクトリ以下のファイルの拡張子の数を数えなければならなくなったのでpythonで書いた。ディレクトリツリーを再帰的に降下するためのモジュールos.walkがあるので比較的楽ではあったけどジェネレータを返す関数なので戸惑った。

# walking.py
import os

# basefunction to walking down directory tree with doing something.
# argument "func" is one argument function.

def walking(func, directory="."):
    nodes = []
    # generator is difficult.. I'm always confusing.
    directory = os.path.abspath(directory)
    for t in os.walk(directory):
	tree = t[0]
	nodes += [tree + os.sep + dirent for dirent in [x for x in t[2]]]
    for node in nodes:
	func(node)
def countext(dir="."):
    dic = {}
    def f(file):
	ext = os.path.splitext(file)[1] # "python.txt" => ("python", ".txt")
	if ext in dic:
	    dic[ext] += 1 
	else:
	    dic[ext] = 1 # create new key
    walking(f, dir)
    dic.keys().sort()
    for n in dic.keys():
	print n + "\t%d" %dic[n]

if __name__ == '__main__':
    import sys
    if len(sys.argv) == 1:
        target = "."
    if len(sys.argv) == 2:
        target = sys.argv[1]
    countext(target)

カレントディレクトリ以下の拡張子.txtの数を取得するには
$ python walking.py | grep "\.txt"

適当に関数を付け足す事もできる。以下の関数はatime, mtime, ctimeを表示する。

def amctime(dir="."):
    import time
    from stat import ST_ATIME, ST_MTIME, ST_CTIME
    t = [ST_ATIME, ST_MTIME, ST_CTIME]
    def f(file):
	st = os.stat(file)
	atime, mtime, ctime = [time.ctime(st[x]) for x in t]
	print ",".join([file, atime, mtime, ctime])
    walking(f, dir)