磁盘使用脚本

时间:2018-08-01 22:49:03

标签: python diskspace

某处事情停止了。目的是在未提供参数的情况下显示当前磁盘使用情况,在作为参数提供的情况下显示目录的使用情况,并在给出--all参数的情况下显示所有子目录的磁盘使用情况。这是我到目前为止所得到的。由于某种原因,现在在为目录提供"-d"时失败。

#!/usr/bin/env python

import os 
import sys 
import subprocess 
import getopt 
from humanize import naturalsize

def get_size(start_path = '.'):
    total_size = 0
    for dirpath, dirnames, filenames in os.walk(start_path):
        for f in filenames:
            fp = os.path.join(dirpath, f)
            total_size += os.path.getsize(fp)
    return total_size

def get_immediate_subdirectories(a_dir):
    return [name for name in os.listdir(a_dir)
            if os.path.isdir(os.path.join(a_dir, name))]

def version():
    print ("Version: 1.0")

def usage():
    print ("Usage: disk_usage.py [-a|--all][-n|--ncdu][-v|--version][directory name]")

def main():
    try:
        opts, args = getopt.getopt(sys.argv[1:], "adhnv", ["all","directory","help","ncdu","version",])
    except getopt.GetoptError as err:
        # print help information and exit:
        print(err)  # will print something like "option -a not recognized"
        usage()
        sys.exit(2)
    for o, a in opts:
        if o in ("-a", "--all"):
            for subdir in get_immediate_subdirectories('.'):
                print ("%s\t\t %s" % (naturalsize(get_size(subdir)),subdir))
                sys.exit()
        elif o in ("-d", "--directory"):
            print (naturalsize(get_size(start_path=sys.argv[1:])))
        elif o in ("-v", "--version"):
            print (version())
            sys.exit()
        elif o in ("-h", "--help"):
            usage()
            sys.exit()
        elif o in ("-n", "--ncdu"):
            os.system('ncdu')
            sys.exit()
        else:
            print (usage())


main()

3 个答案:

答案 0 :(得分:1)

我发现您使用getopt存在一些问题。一种(听起来像是您已经自己弄清楚了)是通过将get_size()传递给start_path=sys.argv[1:]到{{1} }中的所有命令参数。

第二个问题是您没有正确定义传递给start_path的第二个和第三个参数。引用PyMOTW3

  

第二个参数是单个字符选项的选项定义字符串。 如果其中一个选项需要一个参数,则其字母后跟一个冒号。

(重点是我的)

这意味着,为了与list选项一起接受值,您需要使用getopt()而不是已经获得的-d

类似地,对于长样式选项列表中的"ad:hnv"选项:

  

第三个参数(如果使用)应为长型选项名称的序列。长样式选项可以超过单个字符,例如--noarg或--witharg。序列中的选项名称不应包含“-”前缀。 如果任何长选项需要参数,则其名称后缀应为“ =”。

要在此提供支持,还需要您通过"adhnv"

很遗憾,--directory不支持使用可选的option参数。原因很可能是因为它使解析变得模棱两可:例如,如果["all", "directory=", "help", "ncdu", "version"]带有可选参数,而getopt完全是另一个选项,则不清楚如何解释-a

如果您可以忍受这一限制,则以下内容将合并以解决上述问题:

-b

答案 1 :(得分:0)

我想我明白了。第42行包含sys.argv [1:],它返回了一个列表。提供-d选项后,实际上应该是sys.argv [2]来引用目录。

答案 2 :(得分:0)

这里有两个问题。


第一个问题是您使用的getopt错误:

opts, args = getopt.getopt(sys.argv[1:], "adhnv", ["all","directory","help","ncdu","version",])

这将返回选项opts的列表,以及args的列表,其中已滤除选项。但是您将继续使用sys.argv而不是args

print (naturalsize(get_size(start_path=sys.argv[1:])))

在像myprogram -d spam这样的调用中,sys.argv[1:]将是['-d', 'spam']。但是您不希望-d。这就是您首先致电getopts的全部原因。因此,请在此处使用args,而不要使用sys.argv


第二个问题是您正在切片sys.argv[1:],但将其视为单个值而不是值列表来对待。

如果要允许通过-d传递多个目录并对其进行处理,则需要在切片上进行for arg in …:循环。

如果只需要一个目录,则只需索引列表,例如[1],而不是[1:]。尽管,如果您愿意的话,您可能不希望-d是一个布尔型标志,而目录不是arg;您希望-d是一个以目录作为其值的标志。


更一般而言,您可能首先不应该在这里使用getopt。正如the docs所说:

  

注意getopt模块是命令行选项的解析器,其API设计为C getopt()函数的用户熟悉。不熟悉C getopt()函数的用户或想编写更少代码并获得更好帮助和错误消息的用户,应考虑使用argparse模块。

如果您是getopt向导,那么可以肯定的是,即使简单更好,也可以将getopt用于简单项目,而不要学习新知识。但是对于其他任何人,实际上没有充分的理由首先学习getopt,更不用说学习如何调试它的所有时髦之处了。 argparse在各方面都变得更好。而且,如果您不喜欢argparse,则PyPI上有六种替代方法。