1.
İlki:
for f in *; do
echo "$f"
done
denilen dosyalar için başarısız -n, -eve benzeri varyantları -nenedosya adları ters eğik çizgi içeren ve bazı bash dağıtımları ile.
İkinci:
find * -prune | while read f; do
echo "$f"
done
daha fazla vaka için başarısız olur (çağrılan dosyalar ! , -H, -name, (... başlangıç veya bitiş kurusıkı veya yeni satır karakterleri içeren, dosya adları)
Genişleyen kabuk *,find argüman olarak aldığı dosyaları başka bir şey yapmaz Sen de kullanmış olabilir printf '%s\n'olarak hangi yerine printfyerleşik da önleyeceğini olduğunu çok fazla bağımsız değişken potansiyel hata.
2.
Genişlemesi * sıralanır, sıralamaya ihtiyacınız yoksa biraz daha hızlı hale getirebilirsiniz. İçinde zsh:
for f (*(oN)) printf '%s\n' $f
ya da sadece:
printf '%s\n' *(oN)
bashSöyleyebileceğim kadarıyla eşdeğeri yok, o yüzden başvurman gerekiyor find.
3.
find . ! -name . -prune ! -name '.*' -print0 |
while IFS= read -rd '' f; do
printf '%s\n' "$f"
done
(bir GNU / BSD kullanarak yukarıda -print0 standart olmayan bir uzantı kullanılarak).
Bu hala bir bulma komutunun oluşturulmasını ve yavaş bir while readdöngü kullanılmasını içerir, bu nedenle fordosya listesi çok büyük olmadıkça döngü kullanmaktan daha yavaş olacaktır .
4.
Ayrıca, joker karakter genişlemesinin aksine , her dosya findiçin bir lstatsistem çağrısı yapar; bu nedenle, sıralama dışı işlemlerin bunu telafi etmesi olası değildir.
GNU / BSD ile find, aşağıdakileri -maxdepthkazandıran bir optimizasyonu tetikleyecek uzantılarını kullanarak önlenebilir lstat:
find . -maxdepth 1 ! -name '.*' -print0 |
while IFS= read -rd '' f; do
printf '%s\n' "$f"
done
Çünkü finddosya adlarını bulduktan hemen sonra çıkarmaya başlar (stdio çıktı arabelleği hariç), döngüde ne yaparsanız zaman alıcı ve dosya adlarının listesi bir stdio arabasından daha fazlaysa daha hızlı olabilir. / 8 kB). Bu durumda, döngü içindeki işlem findtüm dosyaları bulma işlemini bitirmeden önce başlayacaktır . GNU ve FreeBSD sistemlerinde, stdbufbunun daha erken olmasını sağlamak için kullanabilirsiniz (stdio tamponlamayı devre dışı bırakarak).
5.
Her dosya için komut çalıştırmanın POSIX / standart / taşınabilir yolu yüklemi findkullanmaktır -exec:
find . ! -name . -prune ! -name '.*' -exec some-cmd {} ';'
Durumunda echokabuk bir yerleşik sürümüne sahip olacak şekilde kabuğunda döngü yapmaktan daha az verimli olsa, echoise findyeni bir süreç yumurtlamaya ve yürütmek gerekir /bin/echoher dosya için içinde.
Birkaç komut çalıştırmanız gerekirse, şunları yapabilirsiniz:
find . ! -name . -prune ! -name '.*' -exec cmd1 {} ';' -exec cmd2 {} ';'
Ancak , başarılı cmd2olursa cmd1, yürütüldüğüne dikkat edin .
6.
Her dosya için karmaşık komutları çalıştırmanın kurallı bir yolu, aşağıdakileri içeren bir kabuk çağırmaktır -exec ... {} +:
find . ! -name . -prune ! -name '.*' -exec sh -c '
for f do
cmd1 "$f"
cmd2 "$f"
done' sh {} +
O zamanlar, yerleşik olanını kullandığımızdan ve sürüm mümkün olduğu kadar az çıktığından echoberi verimli olmaya geri döndük .sh-exec +sh
7.
In 200.000 dosyaları ile bir dizin benim testlerde ext4 kısa adlarla, zshbir (paragraf 2.) İlk basit ardından uzak hızlı gereğidir for i in *döngü (her zamanki gibi olsa bashçok daha yavaş diğer kabukları daha o içindir).
findbulduğu dosyaları açmaz. Çok sayıda dosya için sizi burada ısırmayı görebildiğim tek şey ARG_MAX .