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

标签 python bash scp

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

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

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

看起来 pipes.quote(x) 正在转义撇号(它应该转义),但显然语法仍然不正确。我尝试过放弃 pipes.quote(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 将准确解析哪些词。

但为什么首先要从 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)

关于python - 使用python将带有撇号的文件名传递给scp,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13784454/

相关文章:

python - 在 Python GUI 中使用 basemap 作为图形

python - Postgresql:如何将多个列从一个表复制到另一个表?

python - 使用 Openpyxl 在 excel 中复制和重新排列列

bash - 如何在 git 别名(Windows 上的 git-bash)中转义上游的花括号 @{u}? [更新]

linux - 从远程服务器并行复制小文件

python - 如何在 SQLite 中使用 python 语句作为 SELECT 条件?

linux - 将带有日期的 stderr 重定向到来自 Cron 的日志文件

bash - 循环查找文件位置,直到文件存在于 bash 中

bash - 使用 Bash 对三个最新文件进行 scp

java - 让 scp 的状态栏出现在 Java 窗口中