Как передать аргументы скрипта, содержащие кавычки / пробелы?

Я пытаюсь написать скрипт notify-finish это может быть добавлено к любой команде. Когда это будет сделано, он запустит команду, заданную приведенными ниже аргументами, а затем отправит пользователю по электронной почте, когда команда будет завершена. Вот что у меня есть:

PROG=
# Run command given by arguments
$@
ECODE=$?
echo -e "Subject: `hostname`: $PROG finishedrnTo: <$USER>rnrnExited with $ECODErn" | sendmail $USER

это работает большую часть времени, но когда аргументы содержат пробелы, кавычки снял.

пример:

notify-finished rsync -avz source/ user@remote:dest/

не например:

notify-finished rsync -avz -e 'ssh -c blowfish' source/ user@remote:dest/

во втором случае $@ расширяется из к rsync -avz -e ssh -c blowfish source user@remote:dest/, отсутствуют одинарные кавычки. Он не работает ни с двойными кавычками, ни с $*.

после прочтения других сообщений я попытался поместить команду в массив, но я получаю точно такую же проблему:

CMD=(notify-finished rsync -avz -e 'ssh -c blowfish' source/ user@remote:dest/)
${CMD[@]}

как я могу сделать эту работу для всех аргументов?

3 ответов


использовать "$@" С цитаты:

prog=""
"$@"
ecode="$?"
echo "$prog exited with $ecode"

это пройдет каждый аргумент точно так, как он был получен. Если вы не включаете кавычки, каждый элемент будет разделен в соответствии с $IFS:

  • "$@" как "" "" "" ..., передавая каждый элемент как отдельный аргумент.
  • "$*" как " ...", передавая все элементы, объединенные в один аргумент
  • $* и $@ как ..., нарушая вверх по каждому элементу на пробелах, расширяя все глобусы и передавая каждое результирующее слово как отдельный элемент ($IFS).

то же самое верно для массивов, таких как "${array[@]}" и "${array[*]}"


поместите двойные кавычки вокруг подстановок переменных, чтобы они не анализировались (обратите внимание, что это относится ко всем переменным:$@, и $PROG). Также: не ставьте $ перед именем переменной при назначении ему; используйте # для комментариев; и, в последней строке, одинарные кавычки будут препятствовать замене переменных вообще.

PROG=""
shift
# Run program below
"$PROG" "$@"
ECODE=$? # note: this will always be a number, so it doesn't have to be protected with double-quotes
echo -e "Subject: $(hostname): $PROG finished\r\nTo: <$USER>\r\n\r\nExited with $ECODE\r\n' | sendmail "$USER"

ваш скрипт должен быть таким:

# Run program below
PROG="$@"
${PROG}
ECODE=$?
echo -e "Subject: $(hostname): ${PROG} finished\r\nTo: <$USER>\r\n\r\nExited with $ECODE\r\n"

Final Echo command нуждается в двойных кавычках вместо одинарной кавычки ' для интерпретации и расширения $ переменные.

и вы должны заключать аргумент командной строки в двойные кавычки, а также так:

notify-finished "rsync -avz -e 'ssh -c blowfish' source/ user@remote:dest/"