经常磁盘告警,需要反复使用du -sh * 和 cd 来确认那些文件很大,需要删除或清理。
于是写了这个脚本,改吧改吧网上python实现的tree,对结果进行了排序
保留了原始的tree的功能,且对叶子文件夹大小排序输出,便于从后向前查看那些文件夹太大了~~
#! /usr/bin/env python # -*- coding: gbk -*- ''' @note : tree some path and display the leaf folder size by order @authors : U{peterguo<mailto: [email protected]>} @copyright: tencent @date : 2013-02-25 @version : 1.0.0.1 ''' import os import sys from optparse import OptionParser def dumplog(aStr, strMod="a"): fp = file('run.log', strMod) fp.write(str(aStr) + "\n") fp.close() def get_prefix(fs): u'''get display tags according dir path ''' s = '' for i in range(0,len(fs)): last = (i == len(fs)-1) if fs[i] and last: s = s + '|-' elif fs[i] and not last: s = s + '| ' elif not fs[i] and last: s = s + '.-' else: s = s + ' ' if i != len(fs)-1: s = s + ' ' else: s = s + '-' return s def print_tree(current,fs,if_size,if_nofile): u'''recurise display dirs ''' global d_count,f_count,size,d_file2size,d_dir2size fs.append(True) dirs = [] try: dirs = os.listdir(current) except: print "Exception on listdir [%s], ignore ......" % current for i in range(0,len(dirs)): if os.path.islink(current+os.sep+dirs[i]): continue abs_file = os.path.realpath(current+os.sep+dirs[i]) if i == len(dirs)-1: fs[len(fs)-1] = False if fs[len(fs)-1] and if_nofile: last_flag = True for j in range(i+1,len(dirs)): if os.path.isdir(os.path.realpath(current+os.sep+dirs[j])): last_flag = False break if last_flag: fs[len(fs)-1] = False if os.path.isdir(abs_file): print '%s%s' % (get_prefix(fs),dirs[i]) dumplog('%s%s' % (get_prefix(fs),dirs[i])) if not d_dir2size.has_key(abs_file): d_dir2size[abs_file] = 0; d_count = d_count + 1 print_tree(abs_file,fs[:],if_size,if_nofile) else: try: file_size = os.path.getsize(abs_file) d_file2size[abs_file] = file_size if if_size: size = size + file_size if not if_nofile: print '%s%s' % (get_prefix(fs),dirs[i]) dumplog('%s%s' % (get_prefix(fs),dirs[i])) f_count = f_count + 1 except: pass def print_total(dir_count,file_count,if_size=False,file_size=0): u'''print summary information ''' if not if_size: print u'total %d folder,%d files' % (d_count,f_count) dumplog('total %d folder,%d files' % (d_count,f_count)) else: unit = ('B','KB','MB','GB','TB') i = len(str(size))/3 if i > 4: i = 4 unit_size = 1024 ** i f_size = round(float(size)/unit_size,2) print u' total %d folders,%d files, size %s %s' % (d_count,f_count,f_size,unit[i]) dumplog(' total %d folders,%d files, size %s %s' % (d_count,f_count,f_size,unit[i])) print '' dumplog('') parser = OptionParser() parser.add_option("-p", "--paths", dest="paths", help="path") parser.add_option("-s", "--size", dest="size", action="store_true", default=False, help="size the result") parser.add_option("-f", "--nofile", dest="nofile", action="store_true", default=False, help="ignore file") f_count = 0 d_count = 0 size = 0 d_dir2size = {} #record dir size d_file2size = {} #record file size if __name__ == "__main__": options, args = parser.parse_args() dumplog("start .......", 'wt') if len(args)==0 : print u'can not find target path, default as current path' print os.getcwd() d_dir2size[os.getcwd()] = 0 print_tree(os.getcwd(),[],options.size==True,options.nofile==True) print_total(d_count,f_count,options.size==True,size) else: for path in args: f_count = 0 d_count = 0 size = 0 if not os.path.exists(path): print u'skip',path,u', can not find path.' print '' continue path = os.path.realpath(path) d_dir2size[path] = 0 print path print_tree(os.path.normpath(path),[],options.size==True,options.nofile==True) print_total(d_count,f_count,options.size==True,size) #******************** summary every leaf folder *****************************# for afile in d_file2size.keys(): d_dir2size[os.path.dirname(afile)] += d_file2size[afile] l_out = [] for key in d_dir2size.keys(): if d_dir2size[key] != 0: l_out.append("%10.4f MBytes \t%s" % (d_dir2size[key]/(1024*1024.0), key)) l_out.sort() for item in l_out: print item dumplog(str(item))
输出举例:
python mytree.py -f /usr/local/apache2/ /usr/local/apache2 |--lib | .--pkgconfig |--bin |--build |--include |--modules |--conf | |--extra | |--original | | .--extra | .--soso.d |--htdocs |--error | .--include |--icons | .--small |--logs |--cgi-bin |--man | |--man1 | .--man8 .--manual |--developer |--faq |--howto |--images |--misc |--mod |--platform |--rewrite |--ssl |--style | |--css | |--lang | |--latex | .--xsl | .--util |--programs .--vhosts total 39 folder,1212 files 0.0000 MBytes /usr/local/apache2/htdocs 0.0004 MBytes /usr/local/apache2/conf/soso.d 0.0007 MBytes /usr/local/apache2/lib/pkgconfig 0.0010 MBytes /usr/local/apache2/cgi-bin 0.0013 MBytes /usr/local/apache2/error/include 0.0025 MBytes /usr/local/apache2/manual/style/latex 0.0125 MBytes /usr/local/apache2/manual/style 0.0127 MBytes /usr/local/apache2/conf/original 0.0140 MBytes /usr/local/apache2/manual/faq 0.0154 MBytes /usr/local/apache2/icons/small 0.0210 MBytes /usr/local/apache2/man/man1 0.0311 MBytes /usr/local/apache2/conf/extra 0.0311 MBytes /usr/local/apache2/conf/original/extra 0.0350 MBytes /usr/local/apache2/man/man8 0.0359 MBytes /usr/local/apache2/manual/style/css 0.0946 MBytes /usr/local/apache2/conf 0.1082 MBytes /usr/local/apache2/icons 0.1192 MBytes /usr/local/apache2/manual/images 0.1323 MBytes /usr/local/apache2/manual/rewrite 0.1482 MBytes /usr/local/apache2/error 0.1569 MBytes /usr/local/apache2/manual/developer 0.1682 MBytes /usr/local/apache2/manual/ssl 0.2167 MBytes /usr/local/apache2/manual/platform 0.2469 MBytes /usr/local/apache2/build 0.3739 MBytes /usr/local/apache2/manual/misc 0.3900 MBytes /usr/local/apache2/manual/howto 0.5180 MBytes /usr/local/apache2/manual/vhosts 0.5301 MBytes /usr/local/apache2/manual/programs 1.1219 MBytes /usr/local/apache2/include 2.3524 MBytes /usr/local/apache2/manual 2.6087 MBytes /usr/local/apache2/bin 3.1963 MBytes /usr/local/apache2/lib 5.3836 MBytes /usr/local/apache2/manual/mod 25.7610 MBytes /usr/local/apache2/modules 94.4569 MBytes /usr/local/apache2/logs
参考:http://qingyi.iteye.com/blog/1325347
附录:遍历子目录和子文件
def recursive_dir(strPath, strType="file"): lRet = [] list_dirs = os.walk(strPath) for root, dirs, files in list_dirs: for d in dirs: if strType in ("dir", "all"): lRet.append(os.path.join(root, d)) for f in files: if strType in ("file","all"): lRet.append(os.path.join(root, f)) return lRet