【问题标题】:Python Subprocess Error in using "cp"使用“cp”时的Python子进程错误
【发布时间】:2013-07-26 16:38:48
【问题描述】:

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

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

附:我阅读了Problems with issuing cp command with Popen in Python 中发布的问题,它建议使用shell = True 选项,正如我提到的那样,这对我不起作用:(

【问题讨论】:

    标签: python subprocess cp


    【解决方案1】:

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

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

    The docs say:

    在 shell=True 的 Unix 上,shell 默认为 /bin/sh。如果 args 是 string,字符串指定要通过shell执行的命令。 这意味着字符串必须完全按照它的格式进行格式化 在 shell 提示符下键入时。这包括,例如,引用或 反斜杠转义带有空格的文件名。如果 args 是 序列,第一项指定命令字符串,任何 附加项将被视为 shell 的附加参数 自己。

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

    【讨论】:

    • 如果我想做这样的调用:subprocess.call(["cp","-r", "/home/user/logs", directory_logs]) 其中directory_logs 是一个字符串,其中我有一个现有目录。在这种情况下如何使用shell=True 选项?
    • shell=True 选项由于security concerns强烈反对。我在下面发布了一个更安全的替代方案。
    【解决方案2】:

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

    您在通话中遇到的问题:

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

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

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

    问题在于通配符 (*)。文件系统在testdir1 目录中寻找一个字面名称为'*' 的文件,当然,该目录不存在。

    解决方案是使用shell = True 选项和不引用任何参数来像选择的答案一样拨打电话。

    【讨论】:

    • 很好的解释。帮助我了解发生了什么。
    【解决方案3】:

    我知道shell=True 的选项可能很诱人,但由于security issues,它总是不可取的。相反,您可以结合使用 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-02-22
      • 2016-06-17
      • 1970-01-01
      • 2014-03-30
      • 1970-01-01
      • 2010-10-26
      • 2015-07-13
      相关资源
      最近更新 更多