Этот точный код, кажется, делает то, что я хочу, но не уверен, насколько он безопасен:
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 $$
Просмотрел вопросы по 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
В вашем скрипте ошибка. Возможно, в 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 "$@"