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)
没有成功。
您想使用该-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) 或更高版本中可用
注意2:rsync文档警告说-s| --protect-args可能会成为未来版本的默认值rsync(所以为了面向未来,--no-protect-args如果您不想要它的效果,您可能想开始使用)