如何在远程路径中使用 char ( 传递参数?

Vin*_*rez 2 shell rsync quoting

我正在尝试将带有 rsync 的文件移动到远程位置,

该文件已命名为:DRRS_(H264).mp4

但是当我尝试:

rsync -azR output.mp4 user@server.com:encoded/somepath/DRRS_(H264).mp4
Run Code Online (Sandbox Code Playgroud)

它说:bash:意外标记附近的语法错误`('

但我不明白我应该如何封装它。

我试过 :

rsync -azR output.mp4 user@server.com:"encoded/somepath/DRRS_(H264).mp4"
Run Code Online (Sandbox Code Playgroud)

rsync -azR output.mp4 "user@server.com:encoded/somepath/DRRS_(H264).mp4"
Run Code Online (Sandbox Code Playgroud)

没有成功。

Sté*_*las 7

您想使用该-s|--protect-args选项来rsync.

没有它, 之后的部分:将按原样传递给远程 shell,因此您可以使用该 shell 的构造来构建要传输的列表。

这样,例如,如果您知道远程 shell 是 zsh,则可以执行以下操作:

rsync host:'*(.)' there
Run Code Online (Sandbox Code Playgroud)

仅传输常规文件。或与csh/ bash/ zsh/ ksh

rsync host:'{foo,bar}.txt' there
Run Code Online (Sandbox Code Playgroud)

或者:

rsync file 'host:"$HOME/$(uname)-file"'
Run Code Online (Sandbox Code Playgroud)

现在,这意味着您无法轻松传输具有任意名称的文件。

使用-s,rsync不会将字符串传递给远程 shell。相反,它会在带内将其传递给rsync远程主机上的服务器,因此远程 shell 不会对其进行解释。

(并且)对于大多数 shell 来说是特殊的,您必须使用远程 shell 的语法对其进行转义,这因 shell 而异。

最好是-s改用。

rsync -sazR output.mp4 user@server.com:'encoded/somepath/DRRS_(H264).mp4'
Run Code Online (Sandbox Code Playgroud)

但是,rsync仍然对您传递的字符串执行(它自己的)通配(即使对于目的地!)。所以你仍然不能用rsync. 如果你想处理一个被调用的文件*,你需要用反斜杠将它转义(至少,这一次,这与远程 shell 无关)。

rsync -sazR output.mp4 user@server.com:'\*'
Run Code Online (Sandbox Code Playgroud)

因此,要传输包含在 中的任意名称的文件$1,您需要使用:

file=$1
rsync_escaped_file=$(
  printf '%s.\n' "$file" | sed 's/[[*?]/\\&/g'
)
rsync_escaped_file=${rsync_escaped_file%.}
rsync -s ... "user@host:$rsync_escaped_file"
Run Code Online (Sandbox Code Playgroud)

如果您的本地 shell 是bash并且您知道远程用户的登录 shell 也是bash相同版本,或者,您可以使用printf %q转义远程 shell 的特殊字符而不使用-s

LC_ALL=C printf -v shell_escaped_file %q "$1"
rsync ... "user@host:$shell_escaped_file"
Run Code Online (Sandbox Code Playgroud)

如果您知道远程主机的登录 shell 类似于 Bourne(Bourne、ksh、yash、zsh、bash、ash...)并且您的 ssh 客户端和服务器允许传递LC_*环境变量,您也可以这样做(同样,没有-s) :

LC_FILE=$1 rsync ... 'user@host:"$LC_FILE"'
Run Code Online (Sandbox Code Playgroud)

注1-s| --protect-args选项仅在 3.0.0 (2008) 或更高版本中可用

注意2rsync文档警告说-s| --protect-args可能会成为未来版本的默认值rsync(所以为了面向未来,--no-protect-args如果您不想要它的效果,您可能想开始使用)