Wygląda na to, że kanoniczny sposób na zrobienie tego bash
jest podobny
unset args
while IFS= read -r line; do
args+=("$line")
done < file
cmd "${args[@]}"
lub, jeśli twoja wersja bash ma mapfile
:
mapfile -t args < filename
cmd "${args[@]}"
Jedyną różnicę, którą mogę znaleźć między plikiem mapy a pętlą podczas odczytu w porównaniu z linią jednowierszową
(set -f; IFS=$'\n'; cmd $(<file))
polega na tym, że ten pierwszy przekształci pustą linię w pusty argument, podczas gdy jednowierszowy zignoruje pustą linię. W tym przypadku i tak wolę liniowe zachowanie i tak wolę, więc podwójny bonus za to, że jest kompaktowy.
Chciałbym użyć, IFS=$'\n' cmd $(<file)
ale to nie działa, ponieważ $(<file)
jest interpretowane jako wiersz poleceń, zanim zacznie IFS=$'\n'
obowiązywać.
Chociaż w moim przypadku to nie działa, nauczyłem się, że wiele narzędzi obsługuje linie kończące, null (\000)
zamiast newline (\n)
których znacznie ułatwia to, na przykład, nazwy plików, które są częstymi źródłami takich sytuacji :
find / -name '*.config' -print0 | xargs -0 md5
wysyła listę w pełni kwalifikowanych nazw plików jako argumentów do md5 bez globowania, interpolacji lub czegokolwiek. To prowadzi do niewbudowanego rozwiązania
tr "\n" "\000" <file | xargs -0 cmd
chociaż to również ignoruje puste linie, chociaż przechwytuje linie, które mają tylko białe znaki.