如何使用 'subprocess.check_call' 包含占位符的 运行 `ls` 命令?

How to run `ls` command with 'subprocess.check_call' containing a placeholder?

在python (3.6.8)中你可以使用subprocess.check_call到运行一个命令,例如

import subprocess
subprocess.check_call("ls -l /home/user".split())

在示例中,它打印出主目录的内容:

...
drwx------ 25 user user       4096 Jan 27 16:31 Music
-rw-r--r--  1 user user          0 Jul  9 11:06 nse.file.zip
-rw-rw-r--  1 user user 1938520956 Jul  8 16:59 nse.file.zip.1
-rw-------  1 user user  514916418 Jul  9 11:15 nse.file.zip.part
drwxr-xr-x  5 user user      12288 Mar 11 14:32 Pictures
drwxr-xr-x  8 user user       4096 Mar  9 06:36 Private
drwxr-xr-x  2 user user       4096 Jul 30  2018 Public
...

但是,相比之下,当您想使用占位符一次列出多个文件时,这似乎不再有效:

subprocess.check_call("ls -l /home/user/nse*".split())

subprocess.check_call("ls -l '/home/user/nse*'".split())

在这两种情况下我都会得到一个错误

CalledProcessError: Command '['ls', '-l', '/home/user/nse*']' returned non-zero exit status 2.

CalledProcessError: Command '['ls', '-l', "'/home/user/nse*'"]' returned non-zero exit status 2.

我错过了什么?如何解决这个问题?

你可以这样做:

subprocess.check_call("ls -l /home/user/nse*", shell=True)

您忽略了通配符扩展(了解 * 的含义)不是由 ls 完成而是由 shell 完成的事实。当你 运行 像 shell 中的 ls a*.b 时,是 shell 找出什么是 a*.b 文件,然后将它们传递给 ls。现在你问 ls:给我文件 nse* 字面上 。当然没有这样的文件。

您可以通过shell使用subprocess.check_call(..., shell=True)到运行命令(这将在调用命令之前进行通配符扩展)。

参见:

>>> subprocess.check_call("ls /tmp/foo*".split())
ls: cannot access '/tmp/foo*': No such file or directory
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.7/subprocess.py", line 347, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['ls', '/tmp/foo*']' returned non-zero exit status 2.
>>> subprocess.check_call("ls /tmp/foo*", shell=True)
/tmp/foo.bar  /tmp/foo.c
0

注意在第二种情况下没有 .split() -- 整个字符串作为参数提供给 shell.