Perbarui 2020 untuk Pengguna Linux:
Jika Anda memiliki versi up-to-date dari bash (4.4-alpha atau lebih baik), karena Anda mungkin lakukan jika Anda berada di Linux, maka Anda harus menggunakan jawaban Benjamin W. ini .
Jika Anda menggunakan Mac OS, yang — terakhir saya periksa — masih menggunakan bash 3.2, atau menggunakan bash yang lebih lama, lanjutkan ke bagian berikutnya.
Jawaban untuk bash 4.3 atau sebelumnya
Berikut adalah salah satu solusi untuk mendapatkan output findmenjadi basharray:
array=()
while IFS= read -r -d $'\0'; do
array+=("$REPLY")
done < <(find . -name "${input}" -print0)
Ini rumit karena, secara umum, nama file dapat memiliki spasi, baris baru, dan karakter bermusuhan skrip lainnya. Satu-satunya cara untuk menggunakan finddan memisahkan nama file dengan aman satu sama lain adalah menggunakan -print0yang mencetak nama file yang dipisahkan dengan karakter null. Ini tidak akan merepotkan jika bash readarray/ mapfilefunctions mendukung string yang dipisahkan null, tetapi tidak. Bash readmelakukannya dan itu membawa kita ke loop di atas.
[Jawaban ini aslinya ditulis pada tahun 2014. Jika Anda memiliki versi bash terbaru, lihat pembaruan di bawah.]
Bagaimana itu bekerja
Baris pertama membuat array kosong: array=()
Setiap kali readpernyataan itu dijalankan, nama file yang dipisahkan dengan null dibaca dari input standar. The -rpilihan memberitahu readmeninggalkan karakter backslash saja. The -d $'\0'memberitahu readbahwa input akan null dipisahkan. Karena kita menghilangkan nama untuk read, shell menempatkan masukan ke nama default: REPLY.
The array+=("$REPLY")Pernyataan menambahkan nama file baru untuk array array.
Baris terakhir menggabungkan pengalihan dan substitusi perintah untuk memberikan keluaran findke masukan standar whileperulangan.
Mengapa menggunakan substitusi proses?
Jika kami tidak menggunakan substitusi proses, loop dapat ditulis sebagai:
array=()
find . -name "${input}" -print0 >tmpfile
while IFS= read -r -d $'\0'; do
array+=("$REPLY")
done <tmpfile
rm -f tmpfile
Di atas, output dari finddisimpan dalam file sementara dan file itu digunakan sebagai input standar untuk loop sementara. Ide substitusi proses adalah membuat file-file sementara tidak diperlukan. Jadi, alih-alih whilemendapatkan loop mendapatkan stdin dari tmpfile, kita bisa mendapatkannya dari stdin <(find . -name ${input} -print0).
Substitusi proses sangat berguna. Di banyak tempat di mana perintah ingin membaca dari sebuah file, Anda dapat menentukan substitusi proses <(...), sebagai ganti nama file. Ada bentuk analogi`` >(...)yang dapat digunakan sebagai pengganti nama file di mana perintah ingin menulis ke file.
Seperti array, substitusi proses adalah fitur bash dan shell tingkat lanjut lainnya. Ini bukan bagian dari standar POSIX.
Alternatif: lastpipe
Jika diinginkan, lastpipedapat digunakan sebagai pengganti proses substitusi (ujung topi: Caesar ):
set +m
shopt -s lastpipe
array=()
find . -name "${input}" -print0 | while IFS= read -r -d $'\0'; do array+=("$REPLY"); done; declare -p array
shopt -s lastpipememberi tahu bash untuk menjalankan perintah terakhir di pipeline di shell saat ini (bukan latar belakang). Dengan cara ini, arraysisa - sisa yang ada setelah pipa selesai. Karena lastpipehanya berpengaruh jika kontrol pekerjaan dimatikan, kita jalankan set +m. (Dalam skrip, sebagai lawan dari baris perintah, kontrol pekerjaan dinonaktifkan secara default.)
Catatan tambahan
Perintah berikut membuat variabel shell, bukan array shell:
array=`find . -name "${input}"`
Jika Anda ingin membuat sebuah array, Anda perlu meletakkan parens di sekitar output find. Jadi, secara naif, seseorang dapat:
array=(`find . -name "${input}"`)
Masalahnya adalah bahwa shell melakukan pemisahan kata pada hasil findsehingga elemen array tidak dijamin sesuai keinginan Anda.
Perbarui 2019
Dimulai dengan versi 4.4-alpha, bash sekarang mendukung -dopsi sehingga loop di atas tidak lagi diperlukan. Sebaliknya, seseorang dapat menggunakan:
mapfile -d $'\0' array < <(find . -name "${input}" -print0)
Untuk informasi lebih lanjut tentang ini, silakan lihat (dan upvote) jawabannya Benjamin W. ini .