当我不向脚本传递选项时,rsync 会复制当前目录

当我不向脚本传递选项时,rsync 会复制当前目录

下面是 Ubuntu 18.04 上的一个脚本,用于将文件从一个目录复制到另一个目录。除了当前目录 ( ) 中的文件/media/rmerriam/Backup/rsync_backup被复制到目标之外,一切正常。它们根本不应该被复制,因为它们从来不在源路径中。

手动执行(有或没有没有-s区别):

rmerriam@mysticlakelinux:/media/rmerriam/test/rsync_backup$ rsync -auv -s ../src/ ../dest
sending incremental file list

sent 59 bytes  received 12 bytes  142.00 bytes/sec
total size is 0  speedup is 0.00
rmerriam@mysticlakelinux:/media/rmerriam/test/rsync_backup$ ls ../dest

执行的脚本没有-s

===========================
./merge.sh
 
 ../src/
 ../dest
rsync -auv  ../src/ ../dest
sending incremental file list
./    <====== added why???
merge.sh
merge_all.sh
merge_backups.sh

sent 3,124 bytes  received 76 bytes  6,400.00 bytes/sec
total size is 2,835  speedup is 0.89
rmerriam@mysticlakelinux:/media/rmerriam/test/rsync_backup$ ls ../dest
merge_all.sh  merge_backups.sh  merge.sh

使用-s选项执行脚本:

rmerriam@mysticlakelinux:/media/rmerriam/test/rsync_backup$ ./merge.sh ../src/ ../dest -s
===========================
./merge.sh
 -s
 ../src/
 ../dest
rsync -auv -s ../src/ ../dest
sending incremental file list
./

sent 66 bytes  received 19 bytes  170.00 bytes/sec
total size is 0  speedup is 0.00
rmerriam@mysticlakelinux:/media/rmerriam/test/rsync_backup$ ls ../dest

结果:手动执行和-s选项没有移动$PWD文件。如果没有-s脚本,则复制文件。

该脚本没有-s添加该./目录作为源目录。为什么?

命令行由 所示,echo并且它们是相同的。为什么脚本中有不同的行为?

这是脚本:

#!/bin/bash

# base script for copying files to the common directory.
# only copies newer files

printf '===========================\n'
printf "$0\n $3\n $1\n $2\n"

echo rsync -auv "$3"    "$1" "$2"
rsync -auv "$3"    "$1" "$2"

以供参考 :rsync version 3.1.2 protocol version 31

答案1

你的脚本中有一个错误。可以说,rsync 中也存在一个错误,因为当你向它传递奇怪的数据时,它会默默地做一些令人惊讶的事情,而最好让它出错。但无论哪种方式,你的脚本都不起作用。

有问题的行是:

rsync -auv "$3"    "$1" "$2"

当脚本 ( "$3") 的第三个参数以 a 开头时-,这是 rsync 的一个选项。但是,当第三个参数不以 a 开头时-(包括脚本只有两个参数(或更少)的情况),这是一个非选项参数。 Rsync 接受多个源目录,因此当"$3"不以 a 开头时-,您要求它复制"$3""$1""$2".例如,

./merge.sh ../src/ ../dest

告诉 rsync 将空字符串复制../src/../dest.

大多数应用程序在查找文件名时都会拒绝空字符串。但是,只要接受空字符串作为文件名,它就表示当前目录。它与相对路径转换为绝对路径的方式一致:如果路径是相对路径(不以 开头/),则在当前工作目录的绝对路径和斜杠前面加上斜杠,您将获得等效的绝对路径。如果将此应用于空字符串(由于它不以斜杠开头,所以它是相对路径),您将获得末尾带有斜杠的当前工作目录,即当前工作目录。

Rsync 接受空字符串作为当前目录。所以它完全按照你所说的去做。

可以说,将空字符串作为参数传递更有可能是一个错误,而不是故意的。指定当前目录的最短且广泛接受的方式是.(点)。因此,可以说 rsync 应该打印一条错误消息,指出参数无效并出错。

您希望您的脚本接受可选的额外选项,但按照您实现它的方式,该额外选项是强制性的。要使其可选,请检查脚本是否有第三个参数。

if [ $# -lt 2 ]; then
  echo >&2 "$0: too few arguments (SRC and DEST are required)"
  exit 120
elif [ $# -eq 2 ]; then
  rsync -auv "$1" "$2"
elif [ $# -eq 3 ]; then
  rsync -auv "$3" "$1" "$2"
else
  echo >&2 "$0: too many arguments (only one OPTIONS argument is permitted)"
  exit 120
fi

但这是一个奇怪的界面:为什么最多接​​受一个选项?你不妨接受任意数量的选项(为什么我不能通过-q --dry-run?)。对于用户来说,这既更容易理解,也更容易实现。此外,约定是传递选项非选项参数,而不是之后。一旦界面被简化为接受任意数量的选项,您可以将代码简化为

rsync -auv "$@"

答案2

去查看问题rsync并发现“空引号将 cwd 添加到 SRC 目录”。我$3对添加额外选项的脚本有争议。通常它是空的,所以这是罪魁祸首。添加-s使得参数非空,因此避免了这个问题。

这次手动运行证实了这个问题:

rsync ""  -auv ../src/ ../dest
sending incremental file list
created directory ../dest
./
merge.sh
merge_all.sh
merge_backups.sh

sent 3,124 bytes  received 106 bytes  6,460.00 bytes/sec
total size is 2,835  speedup is 0.88

相关内容