find: -exec vs xargs (aka “find | xargs basename” neden kesiliyor?)


10

Alt dizinlere yayılmış belirli bir türdeki tüm dosyaları bulmaya çalışıyordum ve benim amacım için sadece dosya adına ihtiyacım vardı. Ben yol bileşeni üzerinden sıyırma denedim basename, ama ile çalışmadı xargs:

$ find . -name '*.deb' -print | xargs basename 
basename: extra operand `./pool/main/a/aalib/libaa1_1.4p5-37+b1_i386.deb'
Try `basename --help' for more information.

Bu varyasyonlardan herhangi biriyle aynı şeyi (tam olarak aynı hata) alıyorum:

$ find . -name '*.deb' -print0 | xargs -0 basename 
$ find . -name '*.deb' -print | xargs basename {}

Öte yandan, bu beklendiği gibi çalışır:

$ find . -name '*.deb' -exec basename {} \;
foo
bar
baz

Bu, güncel Cygwin ve Debian 5.0.3'te olur. Benim teşhisi, xargs'ın bir nedenden dolayı iki giriş satırını basename'e geçirmesidir, ama neden? Burada neler oluyor?

Yanıtlar:


23

Çünkü basenamesadece bir parametre istiyor ... LOTS değil. Ve xargsbirçok parametre yaratır.

Gerçek sorununuzu çözmek için (sadece dosya adlarını listeleyin):

 find . -name '*.deb' -printf "%f\n"

Hangi sadece 'basename' yazdırır (adam bulmak):

 %f     File's name with any leading directories
        removed (only the last element).

1
oooh .... / alnı tokat tekrar / bir "aptallar için bulmak" kitabına ihtiyacım olduğunu düşünüyorum ...
quack quixote

Ben bunun xargsargümanların bir listesini oluşturuyor ve sonra gelen komuta her beslemeleri olduğunu düşündüm ? aksi halde bunun ve arasındaki fark find . -name '*.deb' | basenamenedir?
WindowsMaker

GNU taban -aadının artık bir seçeneği var: "birden çok argümanı destekleyin ve her birine bir ad olarak davranın".
piskopos

1
@WindowsMaker komut bağımsız değişkenlerine xargsdönüştürülür stdin. Bir bakıma, bunun tersi echo, argümanlarını dönüştürür stdout. find ... | xargs -n1 basenameYa da find ... | xargs basename -ave arasındaki fark find ... | basename, önceki ikisinin basenamegöz ardı edilen uygulamalarla çalışmasıdır stdin.
8bittree

19

Bunu dene:

find . -name '*.deb' | xargs -n1 basename

bu bir açıklama değil, bu bir çözüm. ve geçici çözüm bulunan herhangi bir dosya için -exec üzerinden 'basename' olarak adlandırmak kadar iyidir.
akira

4
+1 ... bir açıklama olmasa da, bana gösterdiğiniz xargs anahtarını araştırmamı sağlayacak, bu da sonunda beni sadece akira'nın ve john t'nin cevaplarını okuduğum alnı tokatlama hareketine götürecekti ...
quack quixote

1
Ben böyle yaparım. findKomutun tüm giriş ve çıkışlarını öğrenmek istemiyorum , bu yüzden sadece dosyaları bulmak ve listelemek için kullanıyorum ve diğer her şey için xargs kullanıyorum.
Ryan

4

basename yalnızca tek bir argümanı kabul eder. Kullanılması -execdüzgün her çünkü işleri {}cari dosya adına göre değiştirilir işleniyor ve komut bir kez çalıştırılır eşleşti dosya başına yerine tek seferde basename için argümanlar tüm göndermeye çalışmak yerine,.


3

xargs sadece bir argümanı geçmeye zorlanabilir ...

find . -name '*.deb' -print | xargs -n1 basename

Bu işe yarar, ancak kabul edilen cevap finddaha uygun bir şekilde kullanıyor. xargs basenameDosya konumlarının listesini almak için başka bir komut kullandığım için bu soruyu problemleri ararken buldum . -n1İçin bayrak xargsbenim için nihai bir cevaptı.

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.