bash: 'find'出力を 'readarray'にパイプする


14

私はを使用してファイルを検索しfind、それらのファイルをBash配列に配置して、他の操作(lsまたはなどgrep)を実行できるようにしています。しかしreadarrayfindパイプで出力を読み取っていない理由を理解できません。

現在のディレクトリに2つのファイルがあるfile1.txtとしfile2.txtます。したがって、find出力は次のようになります。

$ find . -name "file*"
./file1.txt
./file2.txt

だから私はそれを2つの要素が文字列である配列にパイプしたいと思います("./file1.txt"そして"./file2.txt"引用符なしで)。

他にもいくつか試してみました:

$ declare -a FILES
$ find . -name "file*" | readarray FILES
$ echo "${FILES[@]}"; echo "${#FILES[@]}"

0

echo出力からわかるように、私の配列は空です。

だから私はここで何が間違っているのですか?の出力を標準入力としてreadarray読み取らずfind、それらの文字列を配列に入れないのはなぜですか?

回答:


21

パイプラインを使用する場合、bashはサブシェルでコマンドを実行します。したがって、配列にはデータが入力されますが、サブシェルにあるため、親シェルはそれにアクセスできません。

プロセス置換を使用します。

readarray FILES < <(find)

名前に改行が含まれているファイルでは機能しないことに注意してください。その場合は、より複雑な構文が必要です。

readarray -d '' < <(find -print0)

3
改行をサポートするために、これで十分です:readarray -d '' < <(find your_args -print0)
VasyaNovikov

6

正しい解決策は次のとおりです。

unset a; declare -a a
while IFS= read -r -u3 -d $'\0' file; do
    a+=( "$file" )        # or however you want to process each file
done 3< <(find /tmp -type f -print0)

これは、GregのBashFAQ 020で詳細に説明されているものと似ており、この回答はをカバーしています。

スペースや改行を含む、奇妙な名前のファイル(名前にNULが含まれていない)には問題はありません。そして、結果は配列に設定されます。これは、さらに処理するのに役立ちます。


これは、私が最初に解決しようとしていた問題のより良い解決策です。私の担当者が15に達するとすぐに+1 :)
villapx '17

3

readarray stdinからも読み取ることができます

readarray FILES <<< "$(find . -name "file*")"; echo "${#FILES[@]}"

これはfind -print0、「予期しない」ファイル名から保護するためには機能しません。
roaima
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.