次の内容を含む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)