bash - yapabilir miyim: bulabilirim… -bu hariç & & o?


23

Find - exec ile çağrılan iki kabuk komutunu mantıksal olarak birleştirmenin bir yolu var mı ?

Mesela foo stringini içeren tüm .csv dosyalarını yazdırabilmek için beraber yapmak istiyorum:

find . -iname \*.csv -exec grep foo {} && echo {} \;

ancak bash "'-exec' için eksik argüman" ile şikayet ediyor


2
Sırasıyla 2 tane kullanabilir -execveya bir tane kullanabilirsiniz -exec sh -c 'grep foo "$0" && printf %s\\n "$0"' {} \;.
jw013

Bu beni tekrar tekrar tetikledi: Her zaman sh(bu durumda {}) iletilen ilk argümanın böyle bir şey olacağını $1ve $0olacağını umuyorum sh. Ama aslında, haklısın, ilk argüman olarak ortaya çıkıyor $0. İlk argümanın çağrılan komutun adı olması, sadece bu durumlarda otomatik olarak uygulanamayan bir kuraldır.
dubiousjim

Belki bu soru ile birleştirilmelidir: unix.stackexchange.com/q/18077/4801
dubiousjim

Yanıtlar:


24

-execbir komutu çalıştıran (kabuk değil) bir komuttur ve komutun sonucuna (sıfır veya sıfır olmayan çıkış durumu) dayanarak doğru veya yanlış olarak değerlendirilir .

Yani:

find . -iname '*.csv' -exec grep foo {} \; -print

olur yazdırmak eğer dosya yolunu grepbulur dosyasında foo. Bunun yerine -printbaşka bir -execyüklem veya başka bir yüklem kullanabilirsiniz.

find . -iname '*.csv' -exec grep foo {} \; -exec echo {} \;

Ayrıca bakınız !ve -oolumsuzlama için operatörleri bulun ve veya .

Alternatif olarak, bir kabuğu aşağıdaki gibi başlatabilirsiniz:

find . -iname '*.csv' -exec sh -c '
   grep foo "$1" && echo "$1"' sh {} \;

Veya her dosya için bir kabuk başlatmak zorunda kalmamak için:

find . -iname '*.csv' -exec sh -c '
  for i do
    grep foo "$i" && echo "$i"
  done' sh {} +

10

Karşılaştığınız sorun, kabuğun önce komut satırını ayrıştırması ve &&operatör tarafından ayrılmış iki basit komutu görmesidir :, find . -iname \*.csv -exec grep foo {}ve echo {} \;. Alıntı &&( find . -iname \*.csv -exec grep foo {} '&&' echo {} \;) o atlar, ama şimdi tarafından yürütülen komut findgibi bir şey grepargümanlarla foo, wibble.csv, &&, echove wibble.csv. İşleci findyorumlayacak bir kabuk çalıştırmanız talimatını vermeniz gerekir &&:

find . -iname \*.csv -exec sh -c 'grep foo "$0" && echo "$0"' {} \;

İlk argüman bundan sonra Not sh -c SOMECOMMANDolduğunu $0değil $1.

Komut çağrılarını gruplayarak her bir dosya için bir kabuk işleminin başlangıç ​​zamanından tasarruf edebilirsiniz -exec … +. İşleme kolaylığı için, bazı kukla değerini geçmesi $0, böylece "$@"numaralandırır dosya adları.

find . -iname \*.csv -exec sh -c 'for x in "$@"; do grep foo "$x" && echo "$x"; done' \ {} +

Kabuk komutu sadece iki program ayrılmış ise &&, findkendisi tarafından iş yapabilirsiniz: Yazma iki ardışık -execeylemler ve eğer ikincisi sadece idam edilecek durum 0 ile ilk çıkış.

find . -iname \*.csv -exec grep foo {} \; -exec echo {} \;

(Bunun yerine getirilebileceği gibi sadece örnekleme amaçlı olduğunu grepve sonuçta elde edilen çıktının yine de özellikle yararlı olmadığını kabul ediyorum .)echo-exec echo-print


2
Bunun için "$ 0" kullanmaktan kaçınma eğilimindeyim, çünkü kabuk tarafından hata mesajlarını görüntülemek için de kullanılıyor. Örneğin, kafa karıştırıcı bir ./some-file: grep: command not foundhata mesajı görebilirsiniz. -exec find sh -c '... "$1"' sh {} \;sorun olmazdı. İkinci bulma komutunuzda bir yazım hatası (ilgili) var.
Stéphane Chazelas 14:12

3

Bu özel durumda ben yapardım:

find . -iname \*.csv -exec grep -l foo \{\} \;

Ya da bir ack varsa :

ack -al -G '.*\.csv' foo

Asıl sorunuzu cevaplamak için, bunun gibi bir şey işe yarayabilir:

find . -iname \*.csv -exec sh -c "grep foo {} && echo {}" \;


3
Bu sonuncu komut yalnızca taşınabilir değil, aynı zamanda dosya yolları kabuk kodu olarak değerlendirildiğinden son derece tehlikelidir.
Stéphane Chazelas

Doğru ack / grep kullanarak denemek ve önlemek için daha fazla neden :)
Dennis Kaarsemaker 13:12

1
jw013'ün alternatifi (soruya yorumda verilen) bu açıdan daha güvenli. (
Gilles'un
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.