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



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

因为我在OpenELEC发行版上运行这个程序(除了userhome之外,最小的HTPC linux发行版,只读文件系统使安装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的正确转义的命令行:

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/.../"""

如果您以编程方式进行操作(例如,使用不推荐使用的pipes.quote),那么根本不要触摸文件名(在上面的示例中,您在文件名周围添加了撇号)。

fp = "/media/sdi1/home/data/bob's file.avi"
fp = "user@host:" + pipes.quote(pipes.quote(fp))
cmdline = "scp -c blowfish -C " + fp + " /storage/downloads/incoming/"
os.system(cmdline)

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

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

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)

它更清楚地表达了意图:控制shell将解析的确切单词。

但是,为什么要从一个外壳开始呢?我们不需要一个,可以拯救当地的逃亡者。要直接使用args生成进程,请使用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)

相关内容

  • 没有找到相关文章

最新更新