在python shell中执行bash的复杂查找命令

时间:2017-10-06 12:33:01

标签: python linux bash shell

我是python的新手。我试图在python中执行一个bash脚本来提取不同文件扩展名的计数。 我尝试了以下命令

import subprocess
output = subprocess.check_output("sudo find . -type f -name '*.*' -exec sh -c 'echo ${0##*.}' {} \; | sort | uniq -c | sort -nr | awk '{print $2 ":" $1}'", shell=True)

但它会引发语法错误。 在bash shell中执行find命令

sudo find . -type f -name '*.*' -exec sh -c 'echo ${0##*.}' {} \; | sort | uniq -c | sort -nr | awk '{print $2 ":" $1}'

输出如下

png:3156
json:333
c:282
svg:241
zsh:233
js:192
gz:169
zsh-theme:143
ttf:107
cache:103
md:93

那么如何在python代码中获得相同的输出?我当前的方法需要什么修正? 提前致谢

2 个答案:

答案 0 :(得分:3)

如评论中所述,引用双引号的字符串中的任何双引号都需要使用反斜杠进行转义:

import subprocess
output = subprocess.check_output("sudo find . -type f -name '*.*' -exec sh -c 'echo ${0##*.}' {} \; | sort | uniq -c | sort -nr | awk '{print $2 \":\" $1}'", shell=True)

双引号字符串中的单引号没有任何特殊含义(直接在开头除外),因此不允许您避免转义。

详细信息在标题String and Bytes literals from the Python language reference下解释。

如评论中所述,另一个可能更容易阅读的选项是使用三重双引号:

import subprocess
output = subprocess.check_output("""sudo find . -type f -name '*.*' -exec sh -c 'echo ${0##*.}' {} \; | sort | uniq -c | sort -nr | awk '{print $2 ":" $1}'""", shell=True)

虽然这回答了这个问题,但为了便于阅读和维护,我建议用Python完全替换它,如另一个答案所示。

答案 1 :(得分:2)

顺便说一句,你可以尝试在纯Python中做同样的事情。 这是一个最小的代码:

import os

def count_all_ext ( path ):
    res = {}
    for root,dirs,files in os.walk( path ):
        for f in files :
            if '.' in f :
                e = f.rsplit('.',1)[1]
                res[e] = res.setdefault(e,0)+1
    return res.items()


print '\n'.join( '%s:%d'%i for i in count_all_ext('.'))

好吧,与Bash片段相比它很长,但它是Python ......