Схоже, канонічний спосіб зробити це bash
щось подібне
unset args
while IFS= read -r line; do
args+=("$line")
done < file
cmd "${args[@]}"
або, якщо ваша версія bash має mapfile
:
mapfile -t args < filename
cmd "${args[@]}"
Єдина відмінність, яку я можу знайти між картографічним файлом і циклом під час читання, порівняно з однолінійним
(set -f; IFS=$'\n'; cmd $(<file))
полягає в тому, що перший перетворить порожній рядок у порожній аргумент, а однолінійний ігнорує порожній рядок. У цьому випадку поведінка з одним лайнером - це те, що я б хотів у будь-якому випадку, тому подвійний бонус при цьому є компактним.
Я б використовував, IFS=$'\n' cmd $(<file)
але це не працює, оскільки $(<file)
інтерпретується для формування командного рядка до IFS=$'\n'
набрання чинності.
Хоча в моєму випадку це не працює, я тепер дізнався, що багато інструментів підтримують кінцеві рядки, null (\000)
замість newline (\n)
яких значно полегшує це при роботі з, скажімо, іменами файлів, які є загальними джерелами цих ситуацій. :
find / -name '*.config' -print0 | xargs -0 md5
подає список повнокваліфікованих імен файлів як аргументів до md5 без будь-якої глобалізації чи інтерполяції чи іншого. Це призводить до не вбудованого рішення
tr "\n" "\000" <file | xargs -0 cmd
Хоча це теж ігнорує порожні рядки, хоча це і фіксує рядки, які мають лише пробіли.