【问题标题】:Different results achieved using Python's os.walk function and ls command使用 Python 的 os.walk 函数和 ls 命令获得不同的结果
【发布时间】:2012-08-08 04:08:25
【问题描述】:
#!/bin/python
import os
pipe=os.popen("ls /etc -alR| grep \"^[-l]\"|wc -l")         #Expr1
a=int(pipe.read())
pipe.close()
b=sum([len(files) for root,dirs,files in os.walk("/etc")])  #Expr2
print a
print b
print "a equals to b ?", str(a==b)  #False
print "Why?"

Expr1的功能和Expr2的功能有什么区别? 我认为 Expr1 给出了正确的答案,但不确定。

【问题讨论】:

    标签: python linux bash python-2.7


    【解决方案1】:

    简答:

    ls -laR | grep "^[-l]" 计算指向目录的符号链接。 它匹配任何以l 开头并包含目录符号链接的行。

    相比之下,[files for root, dirs, files in os.walk('/etc')] 不计入目录的符号链接。它忽略所有目录并仅列出文件。


    长答案:

    这是我发现差异的方法:

    import os
    import subprocess
    import itertools
    
    def line_to_filename(line):
        # This assumes that filenames have no spaces, which is a false assumption
        # Ex: /etc/NetworkManager/system-connections/Wired connection 1
        idx = line.rfind('->')
        if idx > -1:
            return line[:idx].split()[-1]
        else:
            return line.split()[-1]
    

    line_to_filename 尝试在ls -laR 的输出中查找文件名。

    这定义了expr1expr2,与您的代码基本相同。

    proc=subprocess.Popen(
        "ls /etc -alR 2>/dev/null | grep -s \"^[-l]\" ", shell = True,
        stdout = subprocess.PIPE)         #Expr1
    out, err = proc.communicate()
    expr1 = map(line_to_filename, out.splitlines())
    
    expr2 = list(itertools.chain.from_iterable(
        files for root,dirs,files in os.walk('/etc') if files))  #Expr2
    
    for expr in ('expr1', 'expr2'):
        print '{e} is of length {l}'.format(e = expr, l = len(vars()[expr]))
    

    这会从expr1 中删除也在expr2 中的名称:

    for name in expr2:
        try:
            expr1.remove(name)
        except ValueError:
            print('{n} is not in expr1'.format(n = name))
    

    删除expr1expr2 共有的文件名后,

    print(expr1) 
    

    产量

    ['i386-linux-gnu_xorg_extra_modules', 'nvctrl_include', 'template-dkms-mkdsc', 'run', '1', 'conf.d', 'conf.d']
    

    然后我使用find/etc 中找到这些文件,并试图猜测这些文件有什么不寻常之处。它们是目录(而不是文件)的符号链接。

    【讨论】:

    • 非常感谢您的详尽回答。
    【解决方案2】:

    如果您使用 walk,则忽略错误(请参阅this),并且 ls 会针对每个错误发送一条消息。这些算作单词。

    【讨论】:

    • 错误消息将被发送到标准错误,而不是管道。
    • 如果一切顺利的话,你还有 .. 和 .指望ls。它也必须是 ls -alR /etc ...
    • '''sum([len(files) for root,dirs,files in os.walk("/etc",onerror=some_function)])''' 这能得到正确的吗回答?以及如何处理“some_function”?
    【解决方案3】:

    在我的机器上,/etc 是 /private/etc 的符号链接,所以ls /etc 只有一行输出。 ls /etc/ 给出 lsos.walk 之间的预期等价。

    【讨论】:

    • /etc 用作示例。实际上它可以是任何目录。而这两种表达方式往往给出不同的答案。
    • 你正在运行什么样的疯狂发行版,符号链接 /etc?
    • @Falmarri NeXTStep 或后代,例如操作系统。 iOS
    猜你喜欢
    • 2017-08-28
    • 1970-01-01
    • 1970-01-01
    • 2019-12-23
    • 2012-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-15
    相关资源
    最近更新 更多