python-tree磁盘大小查看-运维利器

经常磁盘告警,需要反复使用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


你可能感兴趣的:(python-tree磁盘大小查看-运维利器)