Краткий ответ: используйте"$@" (обратите внимание на двойные кавычки). Другие формы очень редко полезны.
"$@"довольно странный синтаксис. Он заменяется всеми позиционными параметрами, как отдельные поля. Если позиционных параметров нет ( $#равен 0), то "$@"расширяется до нуля (не пустой строки, а списка с 0 элементами), если есть один позиционный параметр, то "$@"эквивалентно "$1", если есть два позиционных параметра, то "$@"эквивалентно "$1" "$2", и т.д.
"$@"позволяет передавать аргументы скрипта или функции другой команде. Это очень полезно для упаковщиков, которые делают такие вещи, как установка переменных среды, подготовка файлов данных и т. Д. Перед вызовом команды с теми же аргументами и параметрами, с которыми вызывалась оболочка.
Например, следующая функция фильтрует выходные данные cvs -nq update. Помимо фильтрации выходных данных и состояния возврата (то есть статуса, grepа не статуса cvs), вызов cvssmнекоторых аргументов ведет себя как вызов cvs -nq updateс этими аргументами.
cvssm () { cvs -nq update "$@" | egrep -v '^[?A]'; }
"$@"расширяется до списка позиционных параметров. В оболочках, которые поддерживают массивы, существует аналогичный синтаксис для расширения до списка элементов массива: "${array[@]}"(скобки обязательны, за исключением zsh). Опять же, двойные кавычки несколько вводят в заблуждение: они защищают от разбиения поля и генерации шаблона элементов массива, но каждый элемент массива оказывается в своем собственном поле.
В некоторых древних оболочках имелась ошибка: когда не было позиционных аргументов, они "$@"расширялись до одного поля, содержащего пустую строку, а не до поля. Это привело к обходному пути${1+"$@"} ( ставшему известным благодаря документации Perl ). Затрагиваются только более старые версии фактической оболочки Bourne и реализации OSF1, но ни одна из ее современных совместимых замен (ash, ksh, bash и т. Д.) Не затрагивается. /bin/shне затрагивается ни одной системой, выпущенной в 21-м веке, о которой я знаю (если не считать техобслуживание Tru64, и даже если /usr/xpg4/bin/shэто безопасно, так что #!/bin/shзатрагиваются только сценарии, а не #!/usr/bin/env shсценарии, если ваш PATH настроен на соответствие POSIX) , Короче говоря, это исторический анекдот, о котором вам не нужно беспокоиться.
"$*"всегда расширяется до одного слова. Это слово содержит позиционные параметры, соединенные пробелом между ними. (В более общем случае разделитель - это первый символ значения IFSпеременной. Если значение IFS- пустая строка, разделитель - пустая строка.) Если позиционных параметров нет, то "$*"это пустая строка, если есть два позиционные параметры и IFSимеет значение по умолчанию, то "$*"есть эквивалентное "$1 $2"и т. д.
$@и $*внешние кавычки эквивалентны. Они расширяются до списка позиционных параметров, как отдельные поля, например "$@"; но каждое результирующее поле затем разделяется на отдельные поля, которые обрабатываются как шаблоны подстановочных знаков имени файла, как обычно с расширениями переменных без кавычек.
Например, если текущий каталог содержит три файла bar, bazа fooзатем:
set -- # no positional parameters
for x in "$@"; do echo "$x"; done # prints nothing
for x in "$*"; do echo "$x"; done # prints 1 empty line
for x in $*; do echo "$x"; done # prints nothing
set -- "b* c*" "qux"
echo "$@" # prints `b* c* qux`
echo "$*" # prints `b* c* qux`
echo $* # prints `bar baz c* qux`
for x in "$@"; do echo "$x"; done # prints 2 lines: `b* c*` and `qux`
for x in "$*"; do echo "$x"; done # prints 1 lines: `b* c* qux`
for x in $*; do echo "$x"; done # prints 4 lines: `bar`, `baz`, `c*` and `qux`