Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用python将带有撇号的文件名传递到scp_Python_Bash_Scp - Fatal编程技术网

使用python将带有撇号的文件名传递到scp

使用python将带有撇号的文件名传递到scp,python,bash,scp,Python,Bash,Scp,我试图编写一个python脚本,通过scp将文件从远程服务器复制到本地目录 因为我在OpenELEC发行版上运行它(最小的HTPC linux发行版,除userhome之外的只读文件系统使安装python ssh模块变得不切实际),所以我这样做很难看,只是通过os.system将文件名传递给scp命令 SCPCopy = "scp -c blowfish -C user@host:\"" + pipes.quote(file) + "\" /storage/downloads/incoming/

我试图编写一个python脚本,通过scp将文件从远程服务器复制到本地目录

因为我在OpenELEC发行版上运行它(最小的HTPC linux发行版,除userhome之外的只读文件系统使安装python ssh模块变得不切实际),所以我这样做很难看,只是通过os.system将文件名传递给scp命令

SCPCopy = "scp -c blowfish -C user@host:\"" + pipes.quote(file) + "\" /storage/downloads/incoming/"
SCPCopy = SCPCopy.replace('\n','')
os.system(SCPCopy)
除了包含撇号的文件名外,这是有效的

下面是在带有撇号的文件中传递到os.system的内容的示例:

scp -c blowfish -C user@host:"'/media/sdi1/home/data/bob'"'"'s file.avi'" /storage/downloads/incoming/
错误是:

sh: -c: line 0: unexpected EOF while looking for matching `''
sh: -c: line 1: syntax error: unexpected end of file

它看起来像管道。引号(x)正在转义撇号(它应该转义),但显然语法仍然不正确。我曾经尝试过挖沟管道。引用(x)并用/'替换撇号,但这也没什么用。

因为
scp
是基于
SSH
,所以您给它的文件名也会在远程进行shell转义。因此,你需要逃避两次

shell的正确转义cmdline:

scp -c blowfish -C user@host:"\"/media/sdi1/home/data/bob's file\"" /storage/.../
要生成python字符串,我们必须再添加一级转义。为了保持理智,我们可以使用三重引号:

"""scp -c blowfish -C user@host:"\"/media/sdi1/home/data/bob's file\"" /storage/.../"""
如果以编程方式执行此操作(例如,使用不推荐使用的
管道.quote
),则完全不要触摸文件名(在上面的示例中,您在文件名周围添加了撇号)

这无疑令人困惑。对于一个简单的模型,
pipes.quote
的全部要点是转义输入,以便shell将输入解析为一个单词,该单词等于输入

以下是一种更普遍正确的方法(并产生相同的结果):

它更清楚地表达了意图:控制shell将解析哪些单词

但是为什么首先要从一个外壳开始呢?我们不需要一个,可以在当地救逃犯。要直接使用参数生成进程,请使用
os.exec*
系列中的命令

fp = pipes.quote("/media/sdi1/home/data/bob's file.avi")
commandargs = ["scp", "-c", "blowfish", "-C", "user@host:"+fp, "/storage/downloads/incoming/"]
if os.fork() == 0:
    os.execvp("scp", commandargs)

Python文档说,
pipes.quote
从1.6版开始就被弃用了!我尝试过不使用pipes.quote,只替换撇号,例如:SCPCopy=SCPCopy.replace(“'”,“\”),但是,我得到了相同的错误。请使用
shlex.quote
,不要使用您自己的
\“
。或者您可以将文件重命名为不带撇号。祝你好运。太好了,谢谢你——这很有效。我确实得搬家user@host转到cmdline字符串as pipes.quote是在用户名中添加撇号。编辑:刚刚注意到你的更新-非常有用,谢谢!
fp = "/media/sdi1/home/data/bob's file.avi"
# the filepath argument escaped for ssh/scp on the remote side
fp = pipes.quote(fp)
commandargs = ["scp", "-c", "blowfish", "-C", "user@host:"+fp, "/storage/downloads/incoming/"]
# escape all words for the local shell, and then concatenate space-separated
cmdline = " ".join(map(pipes.quote, commandargs))
os.system(cmdline)
fp = pipes.quote("/media/sdi1/home/data/bob's file.avi")
commandargs = ["scp", "-c", "blowfish", "-C", "user@host:"+fp, "/storage/downloads/incoming/"]
if os.fork() == 0:
    os.execvp("scp", commandargs)