bul -exec cmd {} + vs | xargs


Yanıtlar:


107

Hız farkı önemsiz olacaktır.

Ancak şunlardan emin olmalısınız:

  1. Komut dosyanız hiçbir dosyanın dosya adında boşluk, sekme vb. İçermeyeceğini varsaymaz; ilk versiyon güvenli, ikincisi güvenli değil.

  2. Komut dosyanız, " -" ile başlayan bir dosyayı seçenek olarak ele almaz .

Yani kodunuz şöyle görünmelidir:

find . -exec cmd -option1 -option2 -- {} +

veya

find . -print0 | xargs -0 cmd -option1 -option2 --

1'i görmezden gelebileceğiniz için ilk sürüm daha kısadır ve yazması daha kolaydır, ancak ikinci sürüm daha taşınabilir ve güvenlidir, çünkü " -exec cmd {} +" GNU findutils'te nispeten yeni bir seçenektir (2005'ten beri, birçok çalışan sistem henüz buna sahip olmayacaktır) ve son zamanlarda hatalıydı . -exec cmd {} +Diğer yanıtlardan da görebileceğiniz gibi, birçok kişi bunu " " bilmiyor .


4
-print0 aynı zamanda birçok Linux olmayan sistemde eksik olan bir GNU bulma (ve GNU xargs) seçeneğidir, bu nedenle taşınabilirlik argümanı o kadar geçerli değildir. Sadece -print kullanma ve Xargs arasında -0 kapalı bırakarak ancak olduğu çok taşınabilir.
dannysauer

7
Önemli olan nokta, -print0 olmadan boşluk veya sekme vb. İçeren bir dosya varsa çalışmaz. Bu, "foo -o index.html" gibi bir dosya adı varmış gibi bir güvenlik açığı olabilir, bu durumda -o işlem görür. bir seçenek olarak. Boş dizinde deneyin: "touch - foo \ -o \ index.html; find. | Xargs cat". Şunu alacaksınız: "kedi: geçersiz seçenek - 'o'"
Tometzky

2
Örneği, - içeren bir dosya adıdır. -Print0 olmadan find ./foo -o index.html tükenecektir. Yani belki a ile başlamak - önemli değil, ama sonuç çok az değişti ve çok kullanıcılı bir sistemde, eğer betiğiniz herkes tarafından okunabiliyorsa bir saldırı vektörü sağlayabilir.
bobpaul

2
Burada beni harekete geçiren bir şey hakkında bir not - kullanılması execsonuçları buldukça xargsçıkaracak, öyle görünüyor ki, stdout'a yazmadan önce tüm dizinin aranmasını bekleyecek. Bunu büyük bir dizinde deniyorsanız ve bu xargsişe yaramıyor gibi görünüyorsa sabırlı olmanız önerilir.
FarmerGedden

1
@Motivated Without -print0find, satırsonu ile ayrılmış dosya adlarını döndürür, ancak satırsonu bir dosya adının parçası olabilir ve bu da onu belirsiz hale getirir. Bayt 0 olamaz, bu nedenle güvenli bir ayırıcıdır. Evet - --bunu destekleyen bir komuta eklemek , her zaman kesinlikle gerekli olmasa veya güvensiz olsa bile, argümanlarını kontrol edemediğinizde iyi bir uygulamadır.
Tometzky

7
find . | xargs cmd

daha verimlidir ( her maç için bir kez çalıştırılanın cmdaksine exec, mümkün olduğunca az çalışır cmd). Ancak, dosya adları boşluklar veya ilginç karakterler içeriyorsa sorun yaşarsınız.

Aşağıdakilerin kullanılması önerilmektedir:

find . -print0 | xargs -0 cmd

Bu dosya adları korkak karakterler içeren bile çalışacak ( -print0markaları find, boş karakter sonlandırmalı maçları yazdırmak -0markaları xargsbu formatı bekliyoruz.)


28
Bu "find. -Exec cmd {} \;" değil ancak "bul. -exec cmd {} +". İkincisi, her seferinde bir dosya çalıştırmayacaktır.
Tometzky

2
xargsEşleşen dosya yoksa (veya birkaç tane) ve cmdher dosya için yapacak çok şeyi yoksa , yaklaşımın aslında önemli ölçüde daha yavaş olduğunu unutmayın . Örneğin, boş bir dizinde çalıştırıldığında, tek bir xargsişlem yerine iki işlemin başlatılması gerektiğinden sürüm en az iki kat daha fazla zaman alacaktır. (Evet, fark genellikle * nix'te algılanamaz, ancak bir döngüde önemli olabilir; veya bir süre Windows'ta deneyin ...)
SamB

2

Modern'in xargssürümleri genellikle paralel boru hattı yürütmeyi destekler.

Açıkçası, find … -exec ve arasında seçim söz konusu olduğunda bir dönüm noktası olabilir. … | xargs

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.