rsync копирует текущий каталог, когда я не передаю параметр в свой скрипт

Этот точный код, кажется, делает то, что я хочу, но не уверен, насколько он безопасен:

rm foo
mkfifo foo

exec 3<>foo

(
    cat <&3 | while read line; do
       if [[ -n "$line" ]]; then
        echo " [prepend] $line";
       fi
    done &
 )

echo ""  >&3;
echo ""  >&3;
echo "foo" >&3
echo "bar" >&3
echo "baz" >&3


pkill -P $$
0
24.09.2020, 01:55
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
0
18.03.2021, 23:04

В вашем скрипте ошибка. Возможно, в rsync также есть ошибка, потому что он молча делает что-то удивительное, когда вы передаете ему странные данные, тогда как было бы лучше, если бы он выдал ошибку. Но в любом случае ваш скрипт не работает.

Проблемная строка:

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

Когда третий аргумент скрипта("$3")начинается с -, это параметр для rsync. Но когда третий аргумент не начинается с -, что включает в себя случай, когда сценарий имеет только два аргумента (или меньше ), это не аргумент опции -. Rsync принимает несколько исходных каталогов, поэтому, когда "$3"не начинается с -, вы просите его скопировать "$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
18.03.2021, 23:04

Теги

Похожие вопросы