Linux Kullanıcıları için 2020 Güncellemesi:
Eğer Linux'taysanız muhtemelen yaptığınız gibi güncel bir bash sürümüne (4.4-alpha veya daha iyisi) sahipseniz, Benjamin W.'nin cevabını kullanmalısınız .
Son kontrol ettiğimde hala bash 3.2 kullanan veya daha eski bir bash kullanan Mac OS kullanıyorsanız, sonraki bölüme geçin.
Bash 4.3 veya öncesi için yanıt
Çıktıyı findbir bashdiziye almak için bir çözüm :
array=()
while IFS= read -r -d $'\0'; do
array+=("$REPLY")
done < <(find . -name "${input}" -print0)
Bu aldatıcıdır, çünkü genel olarak dosya adlarında boşluklar, yeni satırlar ve diğer komut dosyası düşman karakterleri olabilir. findDosya adlarını kullanmanın ve güvenli bir şekilde birbirinden ayırmanın tek yolu -print0, dosya adlarını bir boş karakterle ayrılmış olarak yazdıran kullanmaktır . Bash'in readarray/ mapfileişlevlerinin boş değerlerle ayrılmış dizgeleri desteklemesi ancak desteklememesi halinde bu pek bir rahatsızlık olmaz. Bash readyapar ve bu bizi yukarıdaki döngüye götürür.
[Bu yanıt ilk olarak 2014'te yazılmıştır. Bash'in yeni bir sürümüne sahipseniz, lütfen aşağıdaki güncellemeye bakın.]
Nasıl çalışır
İlk satır boş bir dizi oluşturur: array=()
İfade her readyürütüldüğünde, standart girdiden boş değerle ayrılmış bir dosya adı okunur. -rSeçenek söyler readyalnız ters eğik çizgi karakterleri bırakmak. , -d $'\0'Girdinin readnull ile ayrıldığını söyler . Biz adını ihmal yana read, kabuk varsayılan adları içine giriş koyar: REPLY.
array+=("$REPLY")İfadesi diziye yeni bir dosya adı ekler array.
Son satır find, whiledöngünün standart girdisinin çıktısını sağlamak için yeniden yönlendirme ve komut ikamesini birleştirir .
Neden süreç ikamesi kullanılıyor?
Süreç ikamesi kullanmadıysak, döngü şu şekilde yazılabilir:
array=()
find . -name "${input}" -print0 >tmpfile
while IFS= read -r -d $'\0'; do
array+=("$REPLY")
done <tmpfile
rm -f tmpfile
Yukarıda findöğesinin çıktısı geçici bir dosyada saklanır ve bu dosya while döngüsüne standart girdi olarak kullanılır. Süreç ikame fikri, bu tür geçici dosyaları gereksiz kılmaktır. Böylece, whiledöngünün stdinini alması yerine, onun stdinini almasını tmpfilesağlayabiliriz <(find . -name ${input} -print0).
Süreç ikamesi oldukça faydalıdır. Bir komutun bir dosyadan okumak istediği birçok yerde <(...), dosya adı yerine işlem ikamesi belirtebilirsiniz . >(...)Komutun dosyaya yazmak istediği bir dosya adı yerine kullanılabilen benzer bir form vardır .
Diziler gibi, işlem ikamesi de bash ve diğer gelişmiş kabukların bir özelliğidir. POSIX standardının bir parçası değildir.
Alternatif: lastpipe
İstenirse lastpipeproses ikamesi yerine kullanılabilir (şapka ipucu: Sezar ):
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 lastpipebash'a mevcut kabuktaki boru hattındaki son komutu çalıştırmasını söyler (arka planda değil). Bu şekilde, arrayboru hattı tamamlandıktan sonra var olan kalıntılar. Çünkü lastpipesadece iş kontrolü kapatılırsa etki eder, koşarız set +m. (Bir komut dosyasında, komut satırının aksine, iş kontrolü varsayılan olarak kapalıdır.)
Ek Notlar
Aşağıdaki komut, bir kabuk dizisi değil, bir kabuk değişkeni oluşturur:
array=`find . -name "${input}"`
Bir dizi oluşturmak istiyorsanız, find'ın çıktısının etrafına parantez koymanız gerekir. Yani, safça, biri şunları yapabilir:
array=(`find . -name "${input}"`)
Sorun, kabuğun sonuçları üzerinde kelime bölme yapmasıdır, findböylece dizinin elemanlarının istediğiniz gibi olacağı garanti edilmez.
2019 Güncellemesi
4.4-alfa sürümünden başlayarak, bash artık -dyukarıdaki döngüye artık gerek kalmaması için bir seçeneği desteklemektedir . Bunun yerine şu kullanılabilir:
mapfile -d $'\0' array < <(find . -name "${input}" -print0)
Bununla ilgili daha fazla bilgi için lütfen Benjamin W.'nin cevabına bakın (ve oy verin) .