У меня есть сценарий Bash, в котором я вызываю rsync
для выполнения резервного копирования на удаленный сервер. Чтобы указать, что резервная копия моей папки «Загрузки», я передаю "'${HOME}/Downloads'"
в качестве аргумента rsync
, который выдает:
rsync -avu '/Volumes/Norman Data/Downloads' me@example.com:backup/
Выполнение команды с переменной, расширенной, как указано выше (через терминал или в скрипте) работает нормально, но из-за пробела в раскрытой переменной и того факта, что кавычки (одиночные тики) игнорируются при включении в переменную, передаваемую как часть аргумента (см. здесь ), единственный способ, которым я могу заставить его не задыхаться в пространстве, это сделать:
stmt="rsync -avu '${HOME}/Downloads' me@examle.com:backup/"
eval ${stmt}
Похоже, что при запуске eval
будут присутствовать некоторые уязвимости на всем, что не на 100% приватно для этот сценарий. Правильно ли я считаю, что должен поступать иначе? Если это так, любые советы для bash начинающего сценария будут с благодарностью.
** РЕДАКТИРОВАТЬ ** - у меня действительно есть немного более сложный вариант использования, чем. пример выше. Для пройденных путей у меня есть массив из них, каждый из которых содержит пробелы, которые я затем объединяю в 1 строковый вид вроде
include_paths=(
"'${HOME}/dir_a'"
"'${HOME}/dir_b' --exclude=video"
)
for item in "${include_paths[@]}"
do
inc_args="${inc_args}" ${item}
done
inc_args
, оцениваемый в '/Volumes/Norman Data/me/dir_a' '/Volumes/Norman Data/me/dir_b' --exclude=video
который я затем пытаюсь передать в качестве аргумента rsync
, но одиночные тики читаются как литералы, и после 1-го /Volumes/Norman
он разрывается из-за пробела.
rsync -avu "${inc_args}" me@example.com:backup/
Использование eval похоже на чтение одиночные галочки как кавычки и выполняются:
rsync -avu '/Volumes/Norman Data/me/dir_a' '/Volumes/Norman Data/me/dir_b' --exclude=video me@example.com:backup/
, как мне нужно. Кажется, я не могу найти другой способ работы.
** РЕДАКТИРОВАТЬ 2 - РЕШЕНИЕ **
Итак, первое, что я нужно было изменить массив include_paths
на:
- убрать одиночные галочки из элементов в двойных кавычках
- переместить любые флаги с указанием пути c флаги (например,
--exclude
) к своим собственным элементам непосредственно после пути, который должен применяться к
Затем я создал массив, содержащий команду rsync
и ее параметры, добавил расширенные массивы include_paths
и exclude_paths
и строка подключения к удаленному хосту.
И, наконец, расширил этот массив, в котором выполнялась вся моя, правильно указанная команда rsync
. В конце концов, модифицированный массив include_paths
имеет вид:
include_paths=(
"${HOME}/dir_a"
"${HOME}/dir_b"
"--exclude=video"
"${HOME}/dir_c"
)
, и я собрал все вместе с:
cmd=(rsync -auvzP)
for item in "${exclude_paths[@]}"
do
cmd+=("--exclude=${item}")
done
for item in "${include_paths[@]}"
do
cmd+=("${item}")
done
cmd+=("me@example.com:backup/")
set -x
"${cmd[@]}"