Bash: pipe 'find' output into 'readarray'

14

Saya mencoba mencari file menggunakan find, dan meletakkan file-file itu ke dalam array Bash sehingga saya bisa melakukan operasi lain pada mereka (misalnya lsatau grepmereka). Tapi saya tidak tahu mengapa readarraytidak membaca findoutput karena disalurkan ke dalamnya.

Katakanlah saya punya dua file di direktori saat ini, file1.txtdan file2.txt. Jadi findoutputnya adalah sebagai berikut:

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

Jadi saya ingin menyalurkannya ke dalam array yang dua elemennya adalah string "./file1.txt"dan "./file2.txt"(tanpa tanda kutip, jelas).

Saya sudah mencoba ini, di antara beberapa hal lain:

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

0

Seperti yang Anda lihat dari echooutput, array saya kosong.

Jadi apa yang sebenarnya saya lakukan salah di sini? Mengapa readarraytidak membaca findkeluaran sebagai input standar dan memasukkan string ke dalam array?

villapx
sumber

Jawaban:

21

Saat menggunakan pipa, bash menjalankan perintah dalam subkulit. Oleh karena itu, array diisi, tetapi dalam subkulit, sehingga shell induk tidak memiliki akses ke sana.

Gunakan substitusi proses:

readarray FILES < <(find)

Perhatikan bahwa itu tidak berfungsi untuk file dengan baris baru di namanya. Jika itu bisa terjadi, Anda perlu sintaks yang lebih rumit:

readarray -d '' < <(find -print0)
choroba
sumber
3
Untuk mendukung baris baru, ini sudah cukup:readarray -d '' < <(find your_args -print0)
VasyaNovikov
6

Solusi yang benar adalah:

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)

Itu mirip dengan yang dijelaskan oleh Greg's BashFAQ 020 secara terperinci dan jawaban ini mencakup .

Tidak memiliki masalah dengan file aneh bernama (yang tidak mengandung NUL dalam nama), dengan spasi atau baris baru. Dan hasilnya diatur dalam sebuah array, yang membuatnya berguna untuk diproses lebih lanjut.

Komunitas
sumber
Hebat, ini adalah solusi yang lebih baik untuk masalah yang saya coba pecahkan sejak awal. +1 segera setelah perwakilan saya mencapai 15 :)
villapx
3

readarray bisa juga baca dari stdin

readarray FILES <<< "$(find . -name "file*")"; echo "${#FILES[@]}"
smac89
sumber
Ini tidak berfungsi find -print0untuk melindungi terhadap nama file yang "tidak terduga".
roaima