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 find
menjadi bash
array:
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 find
dan memisahkan nama file dengan aman satu sama lain adalah menggunakan -print0
yang mencetak nama file yang dipisahkan dengan karakter null. Ini tidak akan merepotkan jika bash readarray
/ mapfile
functions mendukung string yang dipisahkan null, tetapi tidak. Bash read
melakukannya 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 read
pernyataan itu dijalankan, nama file yang dipisahkan dengan null dibaca dari input standar. The -r
pilihan memberitahu read
meninggalkan karakter backslash saja. The -d $'\0'
memberitahu read
bahwa 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 find
ke masukan standar while
perulangan.
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 find
disimpan 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 while
mendapatkan 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, lastpipe
dapat 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 lastpipe
memberi tahu bash untuk menjalankan perintah terakhir di pipeline di shell saat ini (bukan latar belakang). Dengan cara ini, array
sisa - sisa yang ada setelah pipa selesai. Karena lastpipe
hanya 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 find
sehingga elemen array tidak dijamin sesuai keinginan Anda.
Perbarui 2019
Dimulai dengan versi 4.4-alpha, bash sekarang mendukung -d
opsi 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 .