Похоже, канонический способ сделать это bash
что-то вроде
unset args
while IFS= read -r line; do
args+=("$line")
done < file
cmd "${args[@]}"
или, если ваша версия bash имеет mapfile
:
mapfile -t args < filename
cmd "${args[@]}"
Единственное различие, которое я могу найти между mapfile и циклом while-read по сравнению с однострочным
(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
хотя это также игнорирует пустые строки, хотя и захватывает строки, которые имеют только пробелы.