调用子进程时在文件名中引用空格

Posted

技术标签:

【中文标题】调用子进程时在文件名中引用空格【英文标题】:Quote spaces in filename when calling subprocess 【发布时间】:2017-11-19 15:19:07 【问题描述】:

有人想出了在文件名中放置空格的绝妙主意。我需要使用该文件名从 python 执行 scp,这是有问题的,因为 shell 会解析命令,并且 scp 也有一些关于空格的怪癖。这是我的测试代码:

import subprocess
import shlex


def split_it(command):
    return shlex.split(command)
    #return command.split(" ")


def upload_file(localfile, host, mypath):
    command = split_it('scp  :""'.format(localfile, host, mypath))
    print(command)
    res = subprocess.run(command, stdout=subprocess.PIPE)
    return res.stdout.decode()


upload_file("localfile.txt", "hostname", "/some/directory/a file with spaces.txt")

这给出了:

['scp', 'localfile.txt', 'hostname:/some/directory/a file with spaces.txt']
scp: ambiguous target

使用带有command.split(" ")的naive版本:

['scp', 'localfile.txt', 'hostname:"/some/directory/a', 'file', 'with', 'spaces.txt"']
spaces.txt": No such file or directory

正确的、有效的 scp 命令是:

['scp', 'localfile.txt', 'hostname:"/some/directory/a file with spaces.txt"']
    是否有现成的解决方案? 如果不是,那么稳健的做法是什么:
split_it('scp localfile.txt hostname:"/some/directory/a file with spaces.txt"')
# returns ['scp', 'localfile.txt', 'hostname:"/some/directory/a file with spaces.txt"']

【问题讨论】:

相关,虽然不是直接重复:***.com/questions/19858176/… @mkrieger1:链接中的引用正是我在开始时创建 scp 命令的方式。之后麻烦就开始了。 是的,正如那里的最佳答案所述,您需要以某种方式双重转义空格。但我不确定在 Python 中是否有很好的方法来做到这一点。 command = ['scp', localfile, ':'.format(host, shlex.quote(mypath))] @delavnog, any 参数最终会作为数组元素传递给您正在运行的程序(请记住,int main(int argc, char** argv)any 调用新可执行文件时的任何情况,无论它是用什么语言实现的)。你为什么要创建一个可以正确分割成数组的格式的字符串,而不是一开始就指定你真正想要的字符串数组? 【参考方案1】:
command = split_it('scp  :""'.format(localfile, host, mypath))

    不用构建命令字符串,只需要再次split_it,直接构建参数列表。

    要向远程文件路径添加一层引用,请使用shlex.quote(或pipes.quote,如果使用较旧的 Python 版本)。

command = ['scp', localfile, ':'.format(host, shlex.quote(mypath))]

来源/相关帖子:

How to escape spaces in path during scp copy in linux? Python scp copy file with spaces in filename https://docs.python.org/3/library/subprocess.html#popen-constructor

【讨论】:

这似乎不适用于 Windows,当我需要双引号以允许 Windows 解释空格等时,它会添加单引号。如果我对双引号进行硬编码,则 Popen 会将其转换为 \" 和我的脚本很混乱 听起来你应该用minimal example reproducing your problem 提出一个新问题。

以上是关于调用子进程时在文件名中引用空格的主要内容,如果未能解决你的问题,请参考以下文章

管道时在python的子进程模块中使用stdout.close()

什么是父进程和子进程?

什么是子进程和父进程

在 docker 容器中调用 python 子进程时出错

通过子进程调用 GhostScript 无法创建输出文件

Windows批处理 调用程序后 不等待子进程 父进程继续执行命令