Bir dizindeki tüm dosyaları greplemenin daha basit bir yolu var mı?


21

Bir içerik için bütün ağacı aramak istediğimde, kullanıyorum

find . -type f -print0 | xargs -0 grep <search_string>

Bunu performans veya kısalık olarak yapmanın daha iyi bir yolu var mı?


2
@Downvoter: Endişelerinizi paylaşabilirsiniz eğer bu soruyu geliştirmek için mutlu.
Dancrumb

2
Birçok bulma sürümünde yerleşik xargs bulunur: find. türü f-exec fgrep <arama_string> {} +
basit kullanıcı

Yanıtlar:


42

Eğer kontrol edin grepdestekleri -r(seçeneği recurse ):

grep -r <search_string> .

1
Evet ... Sadece stackoverflow.com/questions/16956810/… 'i buldum ve buradaki cevap da bu.
Dancrumb

--exclude-dirperformansını ele almak için bir yorum ekle ve biz bir kazanan var!
Dancrumb

1
Bunun taşınabilir olmadığına dikkat edin, ancak grepson zamanlarda FreeBSD ve Linux dağıtımlarını destekliyor. Ve neden --exclude-dir? Bütün bir ağacı aramak istemedin mi?
Philippos

Adil olan nokta ... --exclude-dirkullanım durumumda aslında kullanışlıdır (çünkü alt ağacın bölümleri büyük, fakat işe yaramaz) ve performans hakkında sorular sordum ... ama haklısın, bu gerekli değil.
Dancrumb

Bu durumda, IIRC'nin GNU'ya --exclude-dirözel olduğunu eklemeliyim grep. (-:
Philippos

13

Bir alt optimal cevap: Bunun yerine boruları koymak find içinegrep sadece koşabilirsiniz

find . -type f -exec grep 'research' {} '+'

ve voila, iki yerine bir komut!

açıklama:

find . -type f

içindeki tüm düzenli dosyaları bulun.

-exec grep 'research'

grep 'araştırma'

{}

bulunan dosya adı

'+'

her dosya adı için bir komut kullanın, dosya adı başına bir kere değil.

Nb: ile ';' dosya adı başına bir kez olurdu.

Bunun dışında, eğer kaynak kodu işlemek için kullanırsanız, içine bakabilirsiniz. ack kod bitlerini kolayca aramak için yapılmış .

ack

Düzenle :

Bu araştırmayı biraz uzatabilirsiniz. İlk önce,-name '' anahtarını .find specifig adlandırma desenli dosyalar için bakmak için.

Örneğin :

  • yalnızca günlüklere karşılık gelen dosyalar: -name '*.log'

  • yalnızca c başlıklarına karşılık gelen dosyalar, ancak dosya adı uzantılarınız için büyük veya küçük harflerle yapışamazsınız: -iname *.c

Nb: gibi grepve ack, -ianahtarı bu durumda duyarsız durumda anlamına gelir.

Bu durumda, grep renksiz ve satır numarasız olarak gösterilir.

Bunu --colorve -ndüğmeleriyle değiştirebilirsiniz (sırasıyla dosyalarda Renkli ve satır numaraları).

Sonunda, şöyle bir şey olabilir:

find . -name '*.log' -type f -exec grep --color -n 'pattern' {} '+'

Örneğin

$ find . -name '*.c' -type f -exec grep -n 'hello' {} '+' 
./test2/target.c:1:hello

5
ackharika ve daha hızlı bir versiyonu ackDİR ag(gümüş arama, geoff.greer.fm/ag )
cfeduke

1
Bunu -name '*.log'daha hızlı olduğu gibi filtre ile tercih ederim .
sdkks

@cfeduke Bunu denemedim, çünkü ag, WSL'deki varsayılan apt havuzlarının bir parçası değil (sahip olduklarınızla çalışmak zorundasınız!)
Pierre-Antoine Guillaume

İşin püf noktası, dosya adının görünmesi için grep'e / dev / null komutunu eklemektir.
ChuckCottrill

İşin püf noktası sadece dizinleri aramak ve sonra -exec grep / dev / null {} / * dizinindeki tüm dosyaları tek bir çatal / exec ile almaktır.
ChuckCottrill

12

Alt dizinlere tekrar girmek istiyorsanız:

grep -R 'pattern' .

Bu -Rseçenek standart bir seçenek değildir, ancak en yaygın grepuygulamalar tarafından desteklenir .


7
GNU grep söz konusu olduğunda sembolik -r-R
ipleri

1
@ AFSHIN Neden sembolik linkleri takip etmek istemiyorsunuz?
Kusalananda

4
@Kusalananda Recursion? Her ne kadar mevcut GNU grepuygulamaları özyinelemeler yakalasa da bence. Aksi halde "ağaç" ile ne demek istediğine bağlı.
Philippos

2
@Philippos IMHO, kullanıcıya çocuk bakıcılığı grepyapmak gibi bir aletin yapması gereken bir şey değildir . Kullanıcı, dizin yapısında sembolik bağlantı döngüler varsa, evet, bu :-) kullanıcının problem
Kusalananda

3
@Kusalananda Ve sistem döngü sağladıysa? Asla kaybolmadım /sys/devices/cpu/subsystem/devices/cpu/subsystem/devices/cpu/...(-XI gibi araçlar bana bakıcılık yapıyor (garip sihir sağlamazlarsa "AI" diyorlar) (-;
Philippos

5

Yukarıda belirtildiği gibi -rveya-R (istenen sembolik bağlantıya bağlı olarak) hızlı bir seçenektir.

ancak -d <action> , zaman zaman yararlı olabilir.

Güzel olan şey -d, sadece geçerli seviyeyi taramak istediğinizde "grep: directory_name: Bir dizin" sesini susturan, atlama komutudur.

$ grep foo * 
grep: q2: Is a directory 
grep: rt: Is a directory 

$ grep -d skip foo *  
$ 

ve tabi ki:

$ grep -d recurse foo * 
(list of results that don't exist because the word foo isn't in our source code
and I wouldn't publish it anyway).  
$ 

Bu -d skipseçenek, başka bir komut dosyasında GERÇEKTEN kullanışlı olduğundan, mecbur kalmanıza gerek yok 2> /dev/null. :)


0

Çok fazla dosyayla uğraşıyorsanız, grep tüm dosyaları alt klasörlerde greplemekten ziyade, araması gereken dosyaları budadığınızda daha hızlı çalışır.

Bazen bu formatı kullanıyorum:

grep "primary" `find . | grep cpp$`

Alt klasörlerine tüm dosyaları bul .o sonundacpp . Sonra "birincil" için bu dosyaları grep.

İsterseniz, bu sonuçları başka bir görüşme çağrısına aktarmaya devam edebilirsiniz:

grep "primary" `find . | grep cpp$` | grep -v "ignoreThis" | grep -i "caseInsensitiveGrep"

1
backtics iyi, modern bir uygulama değil, hepsi eskimiş
Christopher

1
Adlarında özel karakterli dosyalarınız varsa bu durum bozulur. Olduğu gibi çalışmak için çok özel olmak için ne kadar özel olmaları gerektiğini bilmiyorum, ama yaptığınız şey aslında aynı zamanda kötü olan ls'ın çıktısını ayrıştırmakla aynı şey.
CVn
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.