Belli dosya isimleri "find" kullanarak yoksayılmayı nasıl?


143

Favori BASH komutlarımdan biri:

find . -name '*.*' -exec grep 'SearchString' {} /dev/null \;

Belirtilen SearchString için geçerli dizindeki ve altındaki tüm dosyaların içeriğini arar. Bir geliştirici olarak, bu zaman zaman kullanışlı oldu.

Mevcut projem ve kod tabanımın yapısı nedeniyle, bu BASH komutunu, ".svn" içeren bir dizinde veya altındaki dosyaları ya da ".svn" içeren dosyaları aramayarak daha da gelişmiş yapmak istiyorum. ".html" ile bitirin

MAN sayfası bulmak için biraz kafam karıştı. -Prune'u kullanmayı denedim ve bu bana garip davranışlar verdi. Yalnızca .html sayfalarını atlamak için (başlamak için) şunu denedim:

find . -wholename './*.html' -prune -exec grep 'SearchString' {} /dev/null \;

ve umduğum davranışı alamadım. Sanırım -prune noktasını özlüyorum. Bana yardım eder misiniz?

Teşekkürler


1
Just fyi: findbir yerleşik bash komutu değil, ayrı bir programdır
WakiMiko

1
Dosya içindegrep -rl 'SearchString'
emanuele

@ emanuele Merhaba, SuperUser'a (ve Stack Exchange ağına) hoş geldiniz. Bu sorduğum bir soru ve 2 1/2 yıl önce cevaplandı. Tipik olarak, soruya bir cevap eklemek isterseniz, lütfen bunu yorum yapmak yerine en alta kaydırıp yanıtlayarak yapın. Bu sorunun zaten kabul edilmiş bir cevabı (yeşil onay işaretli) olduğundan, cevabınızın çok dikkat çekmesi pek olası değildir. Bilginize.
Cody S

1
Merhaba, bu sorunuzun cevabı değil. Bu sadece bir ipucudur, başlangıçta belirttiğiniz gibi findbir dosyanın içinde arama yapmak için kullanılır .
emanuele

2
FWIW, tüm dosyaları -name '*.*'bulamıyor : yalnızca adlarına sahip olanları (kullanımları genellikle bir DOS-ism, oysa Unix'te normalde sadece bunun için kullanıyorsunuz). Gerçekten hepsini eşleştirmek için, sadece tamamen argüman kaldırın: . Veya sadece dosyalara grep uygulamak (ve dizinleri atlamak) istiyorsanız, o zaman yapın . .*.**find . -exec ...find . -type f -exec ...
Stefan,

Yanıtlar:


197

Belirli adlara sahip dosyalarla eşleşmemek için find () işlevinin negate (!) Özelliğini kullanabilirsiniz:

find . ! -name '*.html' ! -path '*.svn*' -exec grep 'SearchString' {} /dev/null \;

Bu nedenle, ad .html ile bitiyorsa veya yolun herhangi bir yerinde .svn içeriyorsa, eşleşmeyecek ve yürütme yürütülmeyecektir.


1
Hala -name belirtmeliyim ' . 'orada bir yerde mi? Bunu olumsuzluklardan önce mi yoksa olumsuzlamalardan sonra mı yapardım?
Cody S

Eşleşmenizin amacı *.*yalnızca a içeren dosyaları eşleştirmesini sağlamak mıydı .? Bul bir namedirektif yokluğunda tüm dosyalar ile eşleşir , bu yüzden yukarıdaki html ve svn hariç her şeyle eşleşir
Paul

5
Bence -wholename '*.svn*'daha çok istiyorsun -name.
fuenfundachtzig

2
Evet, öyledir, böylece .svndizinler arama sonuçlarının dışında tutulur.
fuenfundachtzig

1
@ Noumenon ! -name '.', bulgular dışında kalmalı ..
Paul

11

Uzun zamandır aynı sorunu yaşıyorum ve farklı durumlarda uygulanabilecek birkaç çözüm var:

  • ack-grepvarsayılan olarak sürüm kontrol dizinlerini ve geçici dosyaları atlayan bir tür "geliştirici grep" dir . Sayfa sadece belirli dosya türlerini aramak için nasıl ve nasıl açıklar kendi tanımlamak .man
  • grep'' kendi ' --excludeve --exclude-dirseçenekleri dosya globlarını ve tekli dizinleri atlamak için çok kolay kullanılabilir .
  • find . \( -type d -name '.svn' -o -type f -name '*.html' \) -prune -o -print0 | xargs -0 grep ... çalışması gerekir, ancak yukarıdaki seçenekler uzun vadede muhtemelen daha az güçlüktür.

9

Aşağıdaki findkomut, adları içeren dizinleri budaır, Dizine inmemesine .svnrağmen, budanmış yol adı yazdırılır ... ( -name '*.svn'nedeni!).

Dizin adlarını şu filtrelerden filtreleyebilirsiniz: grep -d skipki bu, "dizin adları" girişini sessizce atlar.

GNU grep ile -Hyerine kullanabilirsiniz /dev/null. Hafif yan sorunu gibi: \+çok daha hızlı olabilir \;örneğin. 1 milyon tek satırlık dosya \;için 4m20 , \+sadece 1.2 saniye kullanıldı .

Aşağıdaki yöntem xargsyerine kullanılır -execve \ndosya adlarınızın hiçbirinde yeni satır olmadığını varsayar . Burada kullanıldığı xargsgibi, bulduklarıyla aynı \+.

xargsgiriş ayırıcı değiştirerek ardışık boşluk içeren dosya isimleri geçebilir '\n'ile -dseçeneği.

Bu, adları yalnızca bitmeyen dosyaları içeren .svn ve grepli olan dizinleri hariç tutar .html.

find . \( -name '*.svn*' -prune  -o ! -name '*.html' \) |
   xargs -d '\n' grep -Hd skip 'SearchString'

1
\+-Ecec eyleminin bir türevini gösterdiğiniz için teşekkür ederiz . Hafif yan sorunlar için yaşasın!
Christian Long

Elbette +, kabuk için özel bir karakter olmadığından , ondan önce yazmaya gerek yoktur \.
Scott,
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.