我需要使用 scm 将文件从远程主机复制到本地目录,其中文件有空格,否则我通过 ssh 到该主机并 scp 将文件返回来修复问题。但我想知道如何复制该文件,例如本地主机可能没有安装 sshd。
我试过这个:
scp [email protected]:~/download/file\ that\ have\ spaces.txt ~/download/
但出现错误:
scp: /home/kuba/Pobrane/file: No such file or directory
scp: that: No such file or directory
scp: have: No such file or directory
scp: spaces.txt: No such file or directory
我也尝试file\\ that\\ have\\ spaces.txt
过file%20that%20have%20spaces.txt
答案1
SSH 调用服务器上的 shell(无法绕过它)。 scp 调用此 shell 并告诉它需要写入的文件的名称。 scp 的设计方式是将您作为文件名传递的任何内容直接插入到远程 shell 命令中。这意味着,如果文件名中有任何 shell 特殊字符(对于典型的 Unix shell 来说意味着空格)!"#$&'()*-;<=>?@[\]^`{|}~
(其中一些取决于 shell 和名称中的位置),则需要将它们引用两次:一次用于本地 shell,一次用于引用它们。一次用于远程 shell。
这有优点,特别是它允许您指定通配符。它还允许您使用~
远程主目录(但文件名是相对于远程主目录的,因此您可以使用[email protected]:download/…
而不是[email protected]:~/download/…
)。但缺点是当文件名包含特殊字符时您需要小心。如果您想过滤服务器上允许的文件名(尤其是没有 shell 命令权限的受限帐户),您还需要小心。
引用两次的简单方法是在整个名称周围使用单引号,并在需要在远程端保护的每个特殊字符之前使用反斜杠。这不适用于文件名中的单引号;转义那些为四个字符'\''
。在你的例子中:
scp '[email protected]:download/file\ that\ have\ spaces.txt' ~/download/
您使用两个反斜杠的尝试不起作用,因为\\
本地 shell 将其解析为反斜杠后跟分隔参数的空格;您需要将反斜杠-空格发送到远程主机,并且反斜杠和空格都需要保护不被本地shell解析,因此两者前面都需要一个反斜杠,即您需要3个反斜杠和一个空格。
scp [email protected]:download/file\\\ that\\\ have\\\ spaces.txt ~/download/
SFTP 不通过 shell,因此这是避免特殊字符问题的一种方法。SSHFS基于 SFTP 构建并提供直接远程文件访问,因此您可以执行以下操作
mkdir remote
sshfs [email protected]: remote
cp remote/download/file\ that\ have\ spaces.txt ~/download/
fusermount -u remote
rmdir remote
答案2
解决方案是同时使用引号和转义空格:
scp "[email protected]:~/download/file\ that\ have\ spaces.txt" ~/download/