Короткий ответ
"$@" разворачивается в список отдельных аргументов, каждый в своих кавычках, а $* (и "$*") склеивает все аргументы в одну строку через первый символ IFS; без кавычек оба варианта дополнительно "расщепляются" по пробелам, что ломает аргументы с пробелами внутри.
Как это работает подробнее
bash хранит позиционные аргументы как массив, и "$@" — единственный способ передать их дальше поэлементно, сохранив исходные границы; без кавычек shell выполняет word splitting и файловый globbing над результатом подстановки.
Пример кода
example-472.sh
#!/usr/bin/env bash
run() {
echo "Аргументов получено: $#"
for a in "$@"; do
echo " -> [$a]"
done
}
run "file one.txt" "file two.txt"Что использовать на практике
- Рекомендация. правило по умолчанию — всегда писать
"$@"для проброса аргументов в другую команду и всегда заключать в кавычки подстановки переменных и команд ("$var","$(cmd)"), если нет осознанной причины этого не делать. Это особенно критично для путей к файлам, которые могут содержать пробелы.
Подводные камни
- Ошибка. использовать
$@или$*без кавычек и получать "расползание" аргумента с пробелом на несколько; путать"$*"с"$@"в функции, которая должна прозрачно пробрасывать аргументы вызывающей команде.