Sep*_*ero 5 shell special-characters rsync shell-script quoting
我正在尝试为 rsync 创建一个简单的包装器 shell 脚本。当我将文件名发送到我的脚本时,rsync 似乎永远无法识别正确的位置。文件名中有空格。我已经使用引号、双引号、反斜杠引号和使用 rsync -s --protect-args 标志尝试了十几种不同的变体。我终于没有想法了。这是我的脚本的简化版本。
#!/bin/bash
# Example usage:
# pull.sh "file 1" "file 2"
LOCATION="/media/WD100"
all_files=""
for file in "$@"; do
all_files="$all_files:\"$LOCATION/$file\" "
done
# Pull the given files from homeserver to my current directory.
rsync --progress --inplace --append-verify -ave ssh username@homeserver"$all_files" .
Run Code Online (Sandbox Code Playgroud)
我应该以不同的方式写这个吗?如何使这个脚本工作?
更新:
我更改了我的脚本以尝试反映 Chazelas 的答案,但它似乎仍然不起作用。这是我的新代码:
#!/bin/bash
# Example usage:
# pull.sh "file 1" "file 2"
LOCATION="/media/WD100"
all_files=""
for file in "$@"; do
all_files="$all_files\"$LOCATION/$file\" "
done
rsync --progress --inplace --append-verify -0 --files-from=<(printf '%s\0' "$all_files") -ave ssh username@homeserver: .
Run Code Online (Sandbox Code Playgroud)
运行它给了我标准的“使用”输出,最后出现这个错误。
rsync error: syntax or usage error (code 1) at options.c(1657) [server=3.0.9]
rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
rsync error: error in rsync protocol data stream (code 12) at io.c(605) [Receiver=3.0.9]
Run Code Online (Sandbox Code Playgroud)
用:
# prepend "$location" to each element of the `"$@"` array:
for file do
set -- "$@" "$location/$file"
shift
done
rsync ... -0 --files-from=<(printf '%s\0' "$@") user@host: .
Run Code Online (Sandbox Code Playgroud)
或者:
rsync ... -0 --files-from=<(
for file do
printf '%s\0' "$location/$file"
done) user@host: .
Run Code Online (Sandbox Code Playgroud)
为了安全起见。
它通过命名管道将文件列表作为 NUL 分隔列表传递给rsync.
问题是您需要引用文件名,但您不能使用字符串来完成所有这些操作,因为它将所有文件名作为一个长字符串传递给 rsync,字符串内带有引号(而不是单个文件字符串参数) 。
变量 $@ 是 Bash 中的一个数组。发送到rsync时需要将其转换为新的数组。
LOCATION="/media/WD100/"
all_files=()
for file in "$@"; do
all_files+=(":\"$LOCATION$file\"")
done
rsync --progress --inplace --append-verify -ave ssh username@homeserver"${all_files[@]}" .
Run Code Online (Sandbox Code Playgroud)