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


10

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

因此,当我执行rsync -avz /path/to/source/some\ dir/ user@host.tld:/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
尝试使用单引号和双引号。
jftuga 2011年

哈维尔(Javier)也提到了这一点,但最终确实奏效了,因此我在回复他的回答时粘贴了我的工作代码段。
purefusion 2011年

@purefusion考虑将格雷戈里的答案标记为正确。在-s无需解决了该问题适用手动双逃逸。
m000

Answers:


9

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

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

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


8
而赢家是...单引号和双引号!也许在每台服务器上这都是不同的,所以如果其他答案对某些人不起作用,那么也许可以。这是我在rsync命令的远程端使用的成功代码:'user@host.tld:"/path/to/dest/some\ dir/"'
purefusion 2011年

现在,请问一个问题,为什么该方法(在我的服务器上)有效,但其他两个选项都不起作用(只需将路径用双引号引起来,或使用三反斜杠)?如果重要的话,我正在运行CentOS 5。
purefusion 2011年

那没必要。你好吗?您是使用eval还是通过调用函数来运行它?
Mikel

您没有使用单引号和双引号。您正在使用单引号加双引号再加上反斜杠转义符。三级报价。这应该是不必要的。我再问一遍:你运行得怎么样?
Mikel

@哈维尔“我不知道为什么要这么做”。大概是这样,即可进行代字扩展。
Mikel

2

你说的话是在正确的轨道上:

如果我尝试相同的命令并转义反斜杠和空格,以使其超过本地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

在上面的示例中,服务器(dir with spaces)上的第4个参数全部在一行上的事实表明该引用正常运行。

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

另外两个愚蠢的建议:

  • 其他服务器是Linux服务器,那里的默认外壳是什么?
    • 也许它扩展文件名的方式与您预期的不同
  • 您忘记添加-a-r选项了吗?
    • 我看不到你的输出

正如问题的详细信息中所述,我确实确实尝试了您的前两种方法。也许它们只是在我的服务器上不起作用。我也不想弄乱包装器脚本。我试图避免黑客入侵/ usr / bin / ...在任何情况下,确实确实有另一种更具体的引用方式对我有用,所以也许正是我的服务器正在这种方式工作。如果操作系统毕竟是问题的一部分,那么您的建议对于在其他服务器上或未在CentOS上运行的人仍然肯定可行。
purefusion 2011年

那么,您是如何引用它才能使其正常工作的呢?
Mikel

您遗漏了一些重要的细节。请完整地发布您正在运行的实际命令。
Mikel

2

要点答案:

使用-s(保护args)并将路径包含在引号中:

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

适用于空格或破折号。


谢谢!这是一个适当的解决方案,而不是解决方法。
m000

-2

您可以仅将路径用引号引起来。


1
正如您可能在问题的详细信息中看到的那样,我确实已经尝试过了。但是,另一个答案建议使用特定的报价,并且确实可以正常工作。:)
purefusion 2011年

您需要两个引号和反斜杠。
Sridhar Sarnobat '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.