Xargs komutunda> nasıl kullanılır?


160

Bir dizindeki her dosyayı grep ve o grep çıktısını ayrı bir dosyaya yazmama izin verecek bir bash komutu bulmak istiyorum. Benim tahminim böyle bir şey yapmak olurdu

ls -1 | xargs -I{} "grep ABC '{}' > '{}'.out"

ama bildiğim kadarıyla xargs çift tırnakları sevmiyor. Ancak çift tırnak işaretlerini kaldırırsam, komut tüm komutun çıktısını bir dizi ayrı dosya yerine '{}' adlı tek bir dosyaya yeniden yönlendirir.

Herkes xargs kullanarak bunu yapmanın bir yolu biliyor mu? Ben sadece bu grep senaryosunu xargs ile olan sorunumu göstermek için örnek olarak kullandım, böylece xargs kullanmayan çözümler benim için geçerli değil.

Yanıtlar:


201

Bunu yaparken hata yapmayın:

sh -c "grep ABC {} > {}.out"

Bu, funky dosya adları da dahil olmak üzere birçok koşul altında kırılacak ve doğru alıntı yapmak imkansızdır. Kişisel {}zorunluluk hep önlemek kod enjeksiyon böcek komuta tek tamamen ayrı argüman. Yapmanız gereken şey şudur:

xargs -I{} sh -c 'grep ABC "$1" > "$1.out"' -- {}

İçin xargsde geçerlidir find.

Bu arada, -0seçenek olmadan asla xargs kullanmayın (verilerinizi yok etme konusunda endişelenmediğiniz çok nadir ve kontrollü bir kerelik interaktif kullanım için).

Ayrıştırmayın ls. Hiç. Globbing kullanın veya findbunun yerine:http://mywiki.wooledge.org/ParsingLs

findÖzyineleme gerektiren her şey ve diğer her şey için bir glob ile basit bir döngü kullanın :

find /foo -exec sh -c 'grep "$1" > "$1.out"' -- {} \;

veya özyinelemesiz:

for file in *; do grep "$file" > "$file.out"; done

Tırnakların doğru kullanımına dikkat edin.


Oy kaldırıldı ama bir şüphe regd. xargsolmadan kullanmayın -0: bu sadece boru findçıkışını boru ile yaptığınız zaman geçerlidir xargs, değil mi? ne zaman bunu xargs -a <input_file>nasıl kullanırım? Çoğu komutlar grepçıktılar gibi \nve değil, \0.Bu trsorunu çözmek için düşünebildiğim tek yolu , belki bunu düzeltmek için tekrar kullanmaktır . Ancak bunu sadece ile kullanmak neden önemlidir -0?
legends2k

3
@ legends2k çünkü kullanmadığınızda -0, xargsdosya adlarınızı alır ve içindeki tüm boşlukları, tırnak işaretlerini ve ters eğik çizgileri kırar. Sadece xargsbir araç olarak unutmalısın . Çizgileriniz varsa, çizgileri yinelemek için bir bash döngüsü kullanın: while read line; do <command> "$REPLY"; done < file-with-linesveyacommand | while ...
lhunath

1
Vay, bunu bilmiyordum, detay için teşekkürler! Bu nedenle taşınabilirlik için (hepsi xargsGNU olmadığından ), xargsbirlikte kullanılamadığı sürece kaçınılmalıdır -0. Teşekkür ederim.
legends2k

1
Her ne kadar bu özel kullanım durumu için ayrıntılı bir açıklamayı takdir etsem de, soru, xargsher zaman ayrıştırmayı lsveya kullanmayı içermeyen çıktıyı yeniden yönlendirmektir sh -c. Bu, soruyu en ufak bir şekilde cevaplamaz, ancak sorunun karışıklığını ekleyen ilk google sonucudur.
pandasauce

1
@Ihunath, Merhaba, cevabın benim için iyi çalışıyor. Ama hakkında ayrıntılı açıklama veya bağlantılar verebilir misiniz xargs -I{} sh -c 'grep ABC "$1" > "$1.out"' -- {}? Özellikle, gömülü (çift) tırnak kuralları ve sonunda "-" sembolü. Teşekkür ederim
Scott Yang

40

Olmayan bir çözüm xargsşudur:

find . -mindepth 1 -maxdepth 1 -type f -exec sh -c "grep ABC '{}' > '{}.out'" \;

... ve aynı yapılabilir ile xargs , bu çıkıyor:

ls -1 | xargs -I {} sh -c "grep ABC '{}' > '{}.out'"

Düzenleme : Tek tırnak ile sözler sonra eklenen lhunath .


Xargs kullanmak istediğini söyledi. Ben de olmadan bir çözüm yayınladım, ama xargs'a ihtiyaç duyduğunu görünce sildim.
Zifre

Haklısın. Cevabımı yayınlamamın nedeni, işi yapmak için alternatif bir çözümün bulunmasının hiç yoktan daha iyi olmasıydı. İstenen cevabı (yani, sh -c hile) bulmak için beni doğru yola koyduğu ortaya çıkıyor.
Stephan202

14

Örneğin sadece bir örnek olduğunu ve diğer şeyler için> ihtiyacınız olabileceğini düşünüyorum. GNU Paralel http://www.gnu.org/software/parallel/ kurtarmanız olabilir. Dosya adlarınız içermediği sürece ek alıntıya gerek yoktur \ n:

ls | parallel "grep ABC {} > {}.out"

İçinde \ n bulunan dosya adlarınız varsa:

find . -print0 | parallel -0 "grep ABC {} > {}.out"

Ek bir bonus olarak işlerin paralel çalışmasını sağlarsınız.

Daha fazla bilgi edinmek için giriş videolarını izleyin: http://pi.dk/1

10 saniyelik kurulum tam kurulum yapmaya çalışır; bu başarısız olursa, kişisel bir kurulum; bu başarısız olursa, minimal bir kurulum:

$ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \
   fetch -o - http://pi.dk/3 ) > install.sh
$ sha1sum install.sh | grep 3374ec53bacb199b245af2dda86df6c9
12345678 3374ec53 bacb199b 245af2dd a86df6c9
$ md5sum install.sh | grep 029a9ac06e8b5bc6052eac57b2c3c9ca
029a9ac0 6e8b5bc6 052eac57 b2c3c9ca
$ sha512sum install.sh | grep f517006d9897747bed8a4694b1acba1b
40f53af6 9e20dae5 713ba06c f517006d 9897747b ed8a4694 b1acba1b 1464beb4
60055629 3f2356f3 3e9c4e3c 76e3f3af a9db4b32 bd33322b 975696fc e6b23cfb
$ bash install.sh

GNU Parallel kurulu olmayan bir sunucuya taşımanız gerekirse, deneyin parallel --embed.

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.