通过远程 SSH 连接使用 rsync 时转义远程路径中的空格

通过远程 SSH 连接使用 rsync 时转义远程路径中的空格

当使用 SSH 将 rsync 连接到远程服务器时,如何转义远程路径中的空格等?一个简单的反斜杠就可以转义本地 bash 提示符中的空格,但在远程计算机上,空格会被读取为路径中的中断,从而标记该路径的结束。

因此,当我这样做时,远程服务器正在读取它,因为它无法远程找到该目的地,因为实际目的地是“某个目录”而不仅仅是“某个”。rsync -avz /path/to/source/some\ dir/ [email protected]:/path/to/dest/some\ dir//path/to/dest/some/

如果我尝试相同的命令并转义反斜杠和空格以越过本地 bash 提示符并为远程服务器维护反斜杠(总共三个反斜杠:)/path/to/dest/some\\\ dir/,它确实会将反斜杠发送到远程服务器,但远程服务器随后将路径解释为/path/to/dest/some\/而不是/path/to/dest/some\ dir/仍然剥离空格和其后的字符。

如果我尝试用引号括起路径,它的行为几乎相同,实际上在空格处切断路径。因此它也只能绕过本地 bash 提示符。

最初,我使用的路径中包含“ - ”(空格-连字符-空格)段,而远程服务器返回了一个错误,rsync: on remote machine: -: unknown option这正是启动整个空格转义过程的根本原因。

那么我必须做什么才能让它与远程服务器正常工作,而不必从远程路径中删除空格或其他错误字符(如连字符)?

答案1

在启动器计算机上,rsync建立一个命令行,调用远程计算机上的 rsync 目标,然后使用 ssh 发送该命令行....作为单个字符串。该单个字符串被传递给 shell 进行解析、拆分为参数并执行rsync。我不知道为什么要这样做,而不是将(已经拆分、扩展和取消引用的)参数打包到某个二进制安全容器中并发送到远程 rsync。

这意味着你的论点将被解析不同的外壳,引用重新报价因此。通常,我会用双引号将每个参数括起来,然后将整个表达式括在单引号中。有时这还不够,或者如果您希望在本地和远程使用相同的表达式,则可能会很复杂。

在这种情况下,我通常会设置一些具有简单、无空格、全 ASCII 名称的软链接,并使用它。

答案2

问题:

rsync 通过 ssh 使用两枚贝壳运行:一个本地,一个远程。参数 [email protected]:/path/to/dest/some\ dir/首先由本地 shell 解释。因此,它变为[email protected]:/path/to/dest/some dir/。这是传递给远程 shell 的值,远程 shell 会(当然)将其解释为两个单独的参数:[email protected]:/path/to/dest/somedir/


重点答案:

不需要任何花招就能得到想要的结果。rsync 内置了解决方案(除非你使用的是某个古老的版本):

 -s, --protect-args          no space-splitting; only wildcard special-chars

因此,如果添加该-s标志,则仅需为本地 shell 引用您的参数:

rsync -savz user@server:"/my path with spaces/another dir/" "/my destination/"

答案3

当您说出以下话时,您说的是对的:

如果我尝试相同的命令并转义反斜杠和空格以越过本地 bash 提示符并维护远程服务器的反斜杠

这是我发现的最简单的方法:

rsync -av dir\ with\ spaces/ server.tld:"dir\ with\ spaces"

这种方法同样有效。

rsync -av dir\ with\ spaces/ server.tld:dir\\\ with\\\ spaces

您可以发布确切的输出以及您看到的任何错误吗?

您能用rsync包装脚本替换两边吗?

$ sudo su -
# cd /usr/bin
# mv rsync rsync.real
# cat <<'EOF' >rsync
#!/bin/bash
logfile=/home/yourname/rsync.log
date >> "$logfile"
i=1
for arg in "$@"; do
    echo "arg $i: $arg" >> "$logfile"
    i=$((i+1))
done

rsync.real "$@"
EOF
# chmod +x rsync

然后再次运行 rsync,它应该证明这种转义方式有效,例如

客户端:

Sun Feb 13 13:48:12 EST 2011
1: -av
2: dir with spaces/
3: server:dir\ with\ spaces

服务器端:

Sun Feb 13 13:48:13 EST 2011
1: --server
2: -vlogDtpre.iL
3: .
4: dir with spaces

在上面的例子中,服务器上的第 4 个参数(dir with spaces)都在一行上,这说明引用工作正常。

如果这没有帮助,请尝试重新运行rsync -v、 或rsync -vvrsync -vvv。它将为您提供额外的调试信息。

另外两个愚蠢的建议:

  • 另一台服务器是 Linux 服务器吗?那里的默认 shell 是什么?
    • 也许它的文件名扩展方式与你预期的不同
  • 您忘记添加-a-r选项了吗?
    • 如果不看你的输出,我无法判断

答案4

您只需将路径括在引号中即可。

相关内容