【问题标题】:How to use linux command in subprocess python如何在子进程python中使用linux命令
【发布时间】:2018-02-19 03:39:28
【问题描述】:

我有如下的linux命令:

 find /data/*/hr/ -printf "%f: %p: %u: %g %m (%M) \n"

如何在python子进程中使用check_output

我尝试了下面的方法,但没有工作

 file_name = "/data/*/%s/" % (filename)
 get_perm = check_output(["find", file_name, "-printf", '\"%f: %p: %u: %g %m (%M) \n\"'])

我得到的错误:

find: ‘/data/*/hr/’: No such file or directory
Traceback (most recent call last):
  File "handover.py", line 90, in <module>
    get_perm = check_output(["find", file_name, "-printf", '\"%f: %p: %u: %g %m (%M) \n\"'])
  File "/usr/lib64/python2.7/subprocess.py", line 573, in check_output
    raise CalledProcessError(retcode, cmd, output=output)
subprocess.CalledProcessError: Command '['find', '/data/*/hr/', '-printf', '"%f: %p: %u: %g %m (%M) \n"']' returned non-zero exit status 1

【问题讨论】:

  • -printf 后面少了一个逗号
  • 你有输出吗?您是否收到错误消息(即CalledProcessError?)。如果它因为不喜欢 -printf"%f: %p:... 参数而被丢弃,它应该提出一些问题
  • Python 还将字符串中的\n 翻译成文字换行符,当find 得到它时这可能会很奇怪。您还可以通过使用 ' 字符来包装字符串文字来避免转义 " 字符。
  • 编辑帖子并提供输出

标签: python linux unix subprocess


【解决方案1】:

最后,

我找到了下面的方法

cmd = "find /data/*/{}/* -printf \"%f:%p:%u:%g:%m\n\"".format(filename)
info = subprocess.Popen(cmd,stdout=subprocess.PIPE,shell=True)
print info.stdout.read()

这解决了我的问题

【讨论】:

    【解决方案2】:

    您收到此错误是因为指定的文件不存在。如果您直接在 shell 中运行该命令,您将得到相同的响应。

    例如,以下内容按预期工作:

    import subprocess
    import os
    
    file_name = os.path.join(os.getcwd(), 'test.txt')
    with open(file_name, 'w') as f:
        f.write('hello world')
    
    get_perm = subprocess.check_output([
        "find",
         file_name,
         "-printf",
        '"%f: %p: %u: %g %m (%M) \n"'
        ], shell=True)
    
    print(get_perm)
    os.remove(file_name)
    

    根据docs

    如果返回码 [来自 subprocess.check_output] 不为零,则会引发 CalledProcessError。 CalledProcessError 对象将在 returncode 属性中具有返回码,在输出属性中具有任何输出。

    我建议您将 check_output 调用包装在 try..except 中,并捕获 CalledProcessError。

    或者,如果你真的不想处理异常,你可以改为执行命令:

    x=$(find ~/data/*/hr/ -printf "%f: %p: %u: %g %m (%M) \n" 2&gt;/dev/null || true) &amp;&amp; echo $x

    这永远不会返回非零值,并且只会在文件存在时才包含输出。

    编辑 正如迈克尔指出的那样,“*”没有得到扩展。但是,如果您设置shell=True,它会。尝试如下修改您的命令:

     file_name = "/data/*/%s/" % (filename)
     get_perm = check_output(["find", file_name, "-printf", '"%f: %p: %u: %g %m (%M) \n"'], shell=True)
    

    【讨论】:

    • 虽然确实没有找到该文件,但问题很可能是路径中的*应该被展开。
    • @MichaelMior 很好。如果你设置shell=True,它会扩展splat。
    • 你是对的。添加shell=True 是一个简单的解决方案:)
    【解决方案3】:

    当您在命令行上调用时,您的 shell 将在 /data/*/hr/ 中扩展 *。通过check_output 直接调用该函数会导致 find 按字面意思查找目录/data/*/hr/。您可以使用glob 模块在传递给find 之前扩展路径:

    import glob
    
    file_name = "/data/*/%s/" % (filename)
    get_perm = check_output(["find"] + glob.glob(file_name) + ["-printf", '\"%f: %p: %u: %g %m (%M) \n\"'])
    

    glob.glob 只是通过扩展任何*s 和一些其他特殊字符来生成与给定表达式匹配的路径名数组。

    【讨论】:

    • 嗨迈克尔,它工作正常.. 但问题是文件名 "/data/*/fin/" 。如果 fin 不存在。它将列出其他值。如果 fin 没有退出。我希望不会出现这样的文件或目录错误
    • @gopinara 它将列出其他文件,因为您有一个尾部斜杠,find 命令将其解释为您表示要列出 /fin/ 中包含的所有文件/目录。尝试删除尾部斜杠。您还可以指定要查找的类型以将结果限制为仅文件或目录,例如find /data/*/fin -type f。此外, find 的第一个参数通常是您要在其中搜索文件或目录的目录。也许你想要类似find /data/*/fin -type f -name your_file_name.ext
    • 我尝试删除斜线并添加 -type d..same 结果
    • 您可能只想检查glob.glob(file_name) 是否生成一个空数组,如果是,则根本不要运行该命令。
    猜你喜欢
    • 1970-01-01
    • 2022-10-19
    • 2021-12-10
    • 1970-01-01
    • 2019-02-28
    • 2014-08-06
    • 2015-12-19
    • 2020-12-07
    • 1970-01-01
    相关资源
    最近更新 更多