2

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

因为我在 OpenELEC 发行版上运行它(最小的 HTPC linux 发行版,只读文件系统除了 userhome 使得安装 python ssh 模块不切实际),我这样做很丑,只是通过 os 将文件名传递给 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

看起来 pipe.quote(x) 正在转义撇号(应该如此),但显然语法仍然不正确。我已经尝试过放弃 pipe.quote(x) 并用 /' 替换撇号,但这也没有让我有任何收获。

4

1 回答 1

6

由于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 将输入解析为恰好一个 word,它等于 input

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

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 将准确解析哪些单词。

但是为什么首先要从 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)
于 2012-12-09T04:26:51.737 回答