ファイルリストにスペースが含まれているコマンドの引数としてコマンド置換を正しく使用するには?

ファイルリストにスペースが含まれているコマンドの引数としてコマンド置換を正しく使用するには?

次の内容を含むFILESというファイルがあるとします。

/path/to/something
/path/to/something/else
/path/to/something/else/with/a space
/path/to/something/else/again

次のようにコマンド置換を使用しようとすると:head -n 1 $(cat FILES)

私は次のようになります:

head: cannot open 'a' for reading: No such file or directory
head: cannot open 'space' for reading: No such file or directory

この問題は、エスケープ文字\や区切り文字を使用して""解決することはできません。''(なぜかはわかりません……)

これを行う正しい方法は何ですか?

編集する:明らかに私の問題は思ったより簡単です。これは次のようになります。

head "a space" no_space

しかし、これはそうではありません:

FILES='"a space" no_space'; echo $FILES; head $FILES

"aここでは、、space"3 つのファイルで処理されますno_space
それでは...区切り文字を無視しないようにシェルにどのように要求しますか? (またはエスケープ文字)

編集2:

解決策を見つけました:

while read line; do head "$line"; done < FILES

ループを使わない人はいますか?

答え1

ファイル名にスペースを許可する配列(NULまたは改行を除く)に各行(改行で終わる)を配置する正しい解決策は次のとおりです。

$ readarray -t files <FILES

$ printf '<%s>\n' "${files[@]}"
</path/to/something>
</path/to/something/else>
</path/to/something/else/with/a space>
</path/to/something/else/again>

"${files[0]}"その後、最後のインデックスまですべての値を使用できます。

シェル実行分割の影響を避けるために、各引数を引用します。

FILESにリストされている各ファイルの最初の行を取得するには、次のようにします。

$ readarray -t files <FILES
$ head -n1 "${files[@]}"
first line on first file
first line on second file
...
...

答え2

スクリプトの前に使用すると便利ですset -f。ご提案いただいたikkachuに感謝します。

ソリューション1:

環境IFS=$'\n':

IFS=$'\n' ; head -1  $(cat data)

ソリューション2:

別の考えられる解決策は、定義されたパス間に二重引用符を追加することですFILES

"/path/to/something"
"/path/to/something/else"
"/path/to/something/else/with/a space"
"/path/to/something/else/again"

xargs結果を得るのに役立ちます。

cat FILES | xargs head -n1
#or
xargs head -n1 < FILES
#or
xargs head -n1 <<< $(cat FILES)

関連情報