20

我试图使用子进程调用来执行复制操作(下面的代码):

import subprocess
pr1 = subprocess.call(['cp','-r','./testdir1/*','./testdir2/'], shell = True)

我收到一条错误消息:

cp: missing file operand

Try `cp --help' for more information.

当我尝试使用时shell=False,我得到

cp: cannot stat `./testdir1/*': No such file or directory

我该如何解决这个问题?

我正在使用 RedHat Linux GNOME Deskop 版本 2.16.0 和 bash shell 和 Python 2.6

PS 我阅读了在 Python 中使用 Popen 发出 cp 命令的问题中发布的问题,它建议使用shell = True选项,正如我提到的那样,这对我不起作用:(

4

3 回答 3

27

使用时shell=True,将字符串而不是列表传递给subprocess.call

subprocess.call('cp -r ./testdir1/* ./testdir2/', shell=True)

文档说

在 shell=True 的 Unix 上,shell 默认为 /bin/sh。如果 args 是字符串,则该字符串指定要通过 shell 执行的命令。这意味着字符串的格式必须与在 shell 提示符下键入时的格式完全相同。这包括,例如,引用或反斜杠转义文件名,其中包含空格。如果 args 是一个序列,则第一项指定命令字符串,任何附加项都将被视为 shell 本身的附加参数。

所以(在 ​​Unix 上),当一个列表被传递给subprocess.Popen(or subprocess.call) 时,列表的第一个元素被解释为命令,列表中的所有其他元素被解释为shell的参数。由于在您的情况下您不需要将参数传递给 shell,您可以只传递一个字符串作为第一个参数。

于 2013-07-26T12:06:40.337 回答
8

这是一个旧线程,但我只是遇到了同样的问题。

您在此电话中遇到的问题:

subprocess.call(['cp','-r','./testdir1/*','./testdir2/'], shell = False)

是引用了第一个参数之后的每个参数。所以到shell看到这样的命令:

cp '-r' './testdir1/*' './testdir2/'

问题在于通配符 ( *)。文件系统在目录中查找具有文字名称 ' *' 的文件testdir1,该目录当然不存在。

shell = True解决方案是使用选项和不引用任何参数来像选择的答案一样进行呼叫。

于 2015-07-20T18:13:56.047 回答
3

我知道这个选项shell=True可能很诱人,但由于安全问题,它总是不可取的。相反,您可以结合使用 subprocess 和 glob 模块。

对于Python 3.5 或更高版本

import subprocess
import glob

subprocess.run(['cp', '-r'] + glob.glob('./testdir1/*') + ['./testdir2/'])

对于Python 3.4 或更低版本

import subprocess
import glob

subprocess.call(['cp', '-r'] + glob.glob('./testdir1/*') + ['./testdir2/'])
于 2021-04-16T08:16:41.643 回答