Alt dizinleri içeren metni bulmak için “grep” komutu nasıl kullanılır?


373

Belirli bir metin dizesi içeren tüm dosyaları bulmak istiyorum. grepKomut çalışır, ancak ben (benim geçerli dizinde için bunu sadece yapabilirsiniz) her dizin için nasıl kullanılacağını bilmiyorum. Okumayı denedim man grep, ancak herhangi bir yardım vermemiştir.


grep -RIn <yor pattern> * Tüm metin dosyalarında mevcut dizinlerden aşağı arama yapar.

1
İle Joker --include="*.C"seçeneğiyle, @ user311346, @Lekensteyn sayesinde.
Bob Stein,

Geçerli ve tüm alt dizinlerdeki bir dizgiyi tekrar tekrar aramak için find ve grep kombinasyonunu kullanın. Bu wilddiary.com/find-files-containing-my-text
Drona

Yanıtlar:


487

Kullanmak daha iyi olurdu

grep -rl "string" /path

nerede

  • -r(ya da --recursive) seçeneği de tüm alt dizinlere için kullanılır /pathise,
  • -l(veya --files-with-matches) seçeneği, eşleşen dosyaların dosya adlarını yazdırmak için kullanılır; eşleşen satırlara değil (bu, aynı zamanda grepbir dosyayı ilk önce bu seçenekle eşleştirmeyi durdurarak verilen hızı da artırabilir ).

13
Aslında "string" bulmak için kullanılan bir metin deseni ise, bu işlevi kullanmak daha iyidir, aksi halde dize normal ifadelerde anlamı olan bir nokta veya özel karakter içerdiğinde ve yalnızca bir dize olarak bulunması gereken bir nokta olduğunda, sorunlarla karşılaşabilir. olduğu gibi. Sonra "sabit dize" için -rlFanahtarlar kullanırdım -F(ve regexp değil - örneğin). Tabii ki, eğer görev regexps kullanıyorsa, afedersiniz. Elbette, aynı teoriyi -r olmadan da, insanların grep aramalarını "metin" olarak varsaydıklarını görüyorum ve regexp gibi bir anlam ifade eden özel olanların sorunlara yol açabileceğini görüyorum.
LGB

4
-iDavayı görmezden gelen bayrak da var .
Marco Ceppi

3
Sadece --recursiveseçeneği göstermek isterdim , konuşabilecekleri tonlarca seçenek ve kullanım senaryosu var. @ Dmityugov'dan cevap aldım ve cevapsız çalışmak için değiştirildim find.
enzotib

1
@NN: :-) yapıldı
enzotib

3
@ScottBiggs: seçeneği ile--include '*.h'
enzotib 21

167

Dosyalarda eşleşen satırları arıyorsanız, en sevdiğim komut şudur:

grep -Hrn 'search term' path/to/files
  • -H dosya adının yazdırılmasına neden olur (birden fazla dosya arandığında kullanılır)
  • -r özyinelemeli bir arama yapar
  • -n satır numarasının yazdırılmasına neden olur

path/to/files.geçerli dizinde arama yapmak olabilir

Çok faydalı bulduğum diğer seçenekler:

  • -Iikili dosyaları yoksay (tamamlayıcı: -atüm dosyaları metin olarak kabul et)
  • -Ftedavi search termbir hazır değil, normal bir ifade olarak
  • -i büyük küçük harf duyarlı arama yapın
  • --color=alwaysboruları geçerken bile renkleri zorlamak için less. lessDestek renkleri yapmak için bu -rseçeneği kullanmanız gerekir :

    grep -Hrn search . | less -r
    
  • --exclude-dir=dir.svnve gibi dizinleri hariç tutmak için kullanışlıdır .git.

Örnek çıktı


13
-HBir klasörde, muhtemel olduğu gibi birden fazla dosya varsa gereksizdir. Aslında, man sayfa diyor-H, --with-filename: Print the file name for each match. This is the default when there is more than one file to search.
enzotib

Bilmiyordum, her zaman beklediğim gibi çalıştı. Dosyaları ararken benim varsayılan komuttur.
Lekensteyn

1
Dosyaları yalnızca .a uzantılı bir dosyada düşünmenin (ve bunu -r ile birleştirmek) mümkün mü?
user2413

6
@ user2413 Deneyin--include '*.*'
Lekensteyn

1
@alper Trygrep --exclude='*~' ...
Lekensteyn

24

Böyle bir şeyi kullanabileceğine inanıyorum:

find /path -type f -exec grep -l "string" {} \;

Yorumlardan açıklama

findVerilen bir yolun alt dizinlerinde dosya ve dizin ve link gibi diğer nesneleri bulmanızı sağlayan bir komuttur. Dosya adlarının yerine getirmesi gereken bir maske belirtmezseniz, tüm dizin nesnelerini numaralandırır.

  • -type f dizinleri değil sadece dosyaları işlemesi gerektiğini belirtir.
  • -exec grepHer bulundu dosya için, bu değiştirerek, bunun için ayrı bir argüman olarak dosya adını geçirmeden, grep komutunu çalıştırın gerektiğini belirten {}dosya adıyla

3
Bilmeyenler için, ekleme -name '*.py', eşleşmeleri '.py' ile biten dosyalarla sınırlandırır.
Daniel F

Bu, grep komutlarında -R uygulanmayan istemcileri kapsar.
Aviose

Eşleşen satırı VE dosya adını yazdırmak istiyorsanız, exec gibi yapın:... -exec bash -c 'grep -r "mystring" {} && echo {}' \;
Donn Lee

doğrudan grep kullanmak için göreceli perf nedir?
jonathan

19

Benim varsayılan komut

grep -Rin string *

Capitol 'R' lskullanıyorum çünkü özyinelemeli olarak kullanıyor. Grep ikisini de kabul ettiğinden, kullanmamak için hiçbir sebep yoktur.

EDIT: HVNSweeting, görünüşe göre -Rnerede olmaz gibi sembolik takip -redecek.


1
Gizli dosyalarda da arama yapmak için, çalıştırın shopt -s dotglob( -s"set" olarak hatırlayın ). Dosyaları kaldırırken dikkatli olun. Dotglob etkinse, rm -r *geçerli dizindeki her şeyi değil, aynı zamanda üstündeki dizini de kaldırdığı için kaldırır ... Dotglob'u devre dışı bırakmak için, shopt -u dotglob("unset") kullanın. Değişiklikler geçicidir, ancak yalnızca geçerli kabuk için geçerlidir.
Lekensteyn

Bunu unuttum. Bunu bir satır için ayarlamanın bir yolu var mı? shopt -s dotglob & <grep cmd> & shopt -y dotglobdaha uygun bir şey gibi bir şey ? Bu şekilde sıfırlama konusunda endişelenmek zorunda
kalmayacağız

Ayrıca, grep -Rin string .bu vakaların çoğunda kullanmak muhtemelen daha kolaydır . Sadece kullanıyorum * çünkü daha doğal geliyor.
user606723

1
özyinelemeli grep yaparsanız, o zaman sadece "." onun yerine "*". dotglob'a gerek yok.
Michał Šrajer

1
Bu kadar oy, kılavuz sayfasındaki söz etmez bir şeydir R, sembolik bağlantıları takip edecek retmez
HVNSweeting

12

Yeni ackbir şeyler denemeye istekliysen, bir şans ver . Geçerli dizini yinelemeli olarak arama komutu string:

ack string

Kurulumu oldukça basittir:

curl http://betterthangrep.com/ack-standalone > ~/bin/ack && chmod 0755 !#:3

(Dizini zaten almış olmanız şartıyla ~/binve tercihen içindedir PATH.)


2
Ya da sadece apt-get install ack-grep (ve
alick

chmodKomuta yapılan son parametreler ne yapar? Bunlar spesifik mi yoksa chmodbash ile ilgili mi ( !#:3bölüm)?
Elliott Darfink,

@ElliottDarfink Bash'in geçmiş özelliğini kullanan - !bir etkinlik tasarlayıcısı . Tekrarlamalardan kaçınmak için oldukça güçlüler. !#:3Şimdiye kadar komut satırının üçüncü belirtecine atıfta, yani ~/bin/ackbu durumda.
Konrad Rudolph

4

Rgrep komutu bu ihtiyaçlara adanmıştır.

Mevcut değilse, böyle alabilirsiniz

mkdir -p ~/bin
cd ~/bin
wget http://sdjf.esmartdesign.com/files/rgrep
chmod +x rgrep

Yukarıda açıklandığı gibi doğrudan varsayılan grep seçeneklerinizi ayarlayabilirsiniz.

Ben şahsen kullanırım

[[  ${#args} -lt 5 && "${args//[[:space:]]/}" == "-i" ]] && args="-Hin"
args="${args:--Hns} --color=auto"

İlgili Konu: rgrep’i her zaman renkle kullanma


rgrep, Ubuntu'da varsayılan olarak kurulan grep paketi tarafından sağlanır.
karel

2

Güncelleme 2:

Bu komut satırı sorunu kullanarak findve grepdüzeltir:

$ find path_to_search_in -type f -exec grep -in searchString {} 2> /dev/null +

--color=<always or auto> renkli çıktı için:

$ find path_to_search_in -type f \
            -exec grep --color=always -in searchString {} 2>/dev/null +

Örnek:

$ find /tmp/test/ -type f -exec grep --color=auto -in "Search string" {} 2>/dev/null +

Aşağıdaki anlık görüntüde bir örnek çalışması: snap1


Güncelleme 1:

Aşağıdaki kodu deneyebilirsiniz; sizin .bashrcveya .bash_aliasesbir komut dosyasındaki bir işlev olarak :

wherein () 
{ 
    for i in $(find "$1" -type f 2> /dev/null);
    do
        if grep --color=auto -i "$2" "$i" 2> /dev/null; then
            echo -e "\033[0;32mFound in: $i \033[0m\n";
        fi;
    done
}

Kullanımı: wherein /path/to/search/in/ searchkeyword

örnek:

$ wherein ~/Documents/ "hello world"

(Not: Aşağıdaki yorumlarda @enzotib tarafından önerildiği gibi, bu, adlarındaki boşlukları içeren dosya / dizinlerle çalışmaz.)


Orijinal yayın

Dizeyi aramak ve arama dizesiyle sadece bu satırın çıktısını almak için:

$ for i in $(find /path/of/target/directory -type f); do \
    grep -i "the string to look for" "$i"; done

Örneğin:

$ for i in $(find /usr/share/applications -type f); \
    do grep -i "web browser" "$i"; done

Arama dizesini içeren dosya adını görüntülemek için:

$ for i in $(find /path/of/target/directory -type f); do \
    if grep -i "the string to look for" "$i" > /dev/null; then echo "$i"; fi; done;

Örneğin:

$ for i in $(find /usr/share/applications -type f); \
    do if grep -i "web browser" "$i" > /dev/null; then echo "$i"; \
    fi; done;

Boşluk içeren dosya adlarında başarısız olur. Başarısızlık, stderr'in gösterilmediği gerçeğiyle gizlenir.
enzotib

@enzotib bunu belirttiğiniz için teşekkürler .. belirtilen işlev için hala çözülmedi .. Yine de bir tane daha astar ekledim ..
kesin olarak

Şimdi cevap, @ dmityugov ile aynı.
enzotib

evet, ama bu anlamda, bu sayfadaki cevapların çoğu, kullandıklarına göre benzerlik gösterirlerse grep, alt kümesiyle findbirlikte kullandıklarına benzerler, grepancak farklı anahtarlar ve ince ayarların farklı bir cevap olarak kabul edecekseniz, Muhtemelen benimki de buraya sığacak .. ya da farklı mısın? son güncelleme aramamda ne isterim: dosya adları, arama tuşu ve satır numarası olan satırlar. çok :) ve daha iyi okunabilirlik için renkli çıktı ve hata filtresi ..
hassas

2

grep( GNU veya BSD )

grepGeçerli klasörü tekrarlayan bir şekilde -rparametresiyle aramak için aracı kullanabilirsiniz :

grep -r "pattern" .

Not: -r- Alt dizinleri tekrar tekrar arayın.

Belirli dosyaları aramak için, aşağıdaki gibi bir genel sözdizimi kullanabilirsiniz :

grep "class foo" **/*.c

Not: globbing seçeneğini ( **) kullanarak , tüm dosyaları belirli bir uzantı veya desen ile tekrarlı olarak tarar. Bu sözdizimi etkinleştirmek için çalıştırın: shopt -s globstar. Ayrıca **/*.*tüm dosyalar (gizli ve uzantı hariç) veya başka bir kalıp için kullanabilirsiniz.

Bağımsız değişkeninizin çok uzun olması durumunda, aramanızı daraltmayı düşünün veya findbunun yerine sözdizimini kullanın:

find . -name "*.php" -execdir grep -nH --color=auto foo {} ';'

Alternatif olarak kullanın ripgrep.

ripgrep

Daha büyük projeler veya büyük dosyalar üzerinde çalışıyorsanız, ripgrepbunun yerine aşağıdakileri kullanmalısınız :

rg "pattern" .

GitHub proje sayfasındaki dokümanları, kurulum adımlarını veya kaynak kodunu kontrol edin .

Sanki başka bir araç daha hızlıdır GNU / BSD grep , ucg, ag, sift, ack, ptbunun üzerine kurulmuş olduğundan, ya da benzer Rust en regex motoru çok hızlı arama yapmak için, SIMD ve saldırgan edebi optimizasyonlar sonlu otomata kullanır.

.gitignoreDosyalarda belirtilen yoksayma modellerini destekler , böylece tek bir dosya yolu aynı anda birden fazla glob düzeniyle eşlenebilir.


Gibi ortak parametreleri kullanabilirsiniz:

  • -i - Duyarsız arama.
  • -I - İkili dosyaları yoksay.
  • -w - Tüm kelimeleri arayın (kısmi kelime eşleşmesinin karşısında).
  • -n - Maçın sırasını göster.
  • -C/ --context(eg -C5) - İçeriği arttırır, böylece çevreleyen kodu görürsünüz.
  • --color=auto - Eşleşen metni işaretleyin.
  • -H - Metnin bulunduğu dosya adını görüntüler.
  • -c- Eşleşen çizgilerin sayısını gösterir. İle birleştirilebilir -H.

1

Bunu, çok az kullanılan bir komut olan xargs kullanarak yapıyorum.

find ./ -type f -print0 | xargs -0 grep 'string_you_are_looking_for'

find ./ size mevcut klasördeki tüm dosyaların tekrarlı bir listesini verir ve sonra bu dosyaların her birinde grep komutunu çalıştıran xargs komutunu çalıştırırsınız.


4
Kullanılması xargsolmadan -print0seçeneği findve -0seçenek için xargsuygun bulunmamaktadır, bu boşluk içeren dosya isimleri üzerinde başarısız olur.
enzotib

@enzotib Yanıtı önerdiğin gibi düzenledim. thank you
αғsнιη

1
@KasiyA: şimdi sorun değil, oyum kaldı.
enzotib

0

Burada pek çok cevap olduğunu biliyorum, ancak dosyaları ararken başka kısıtlamalar eklemek isterseniz alternatif:

find . -type f -exec grep --quiet string_to_look_for {} ';' -print

Bu işe yarıyor, çünkü grepbir sonuç bulduysa 0, aksi takdirde 1 döndürür Örneğin, 1 MB büyüklüğünde ve bir şeyler içeren dosyalar bulabilirsiniz :

find . -type f -exec grep --quiet string_to_look_for {} ';' -size 1M -print

Birden fazla gereksinim için, muhtemelen -OGNU grep'te bulunan optimizer bayrağını kullanmak istersiniz .


0

C, CPP kodunda aranacak bir komut dosyası (kod bulma):

#!/bin/sh

find . \( -iname "*.c" -o -iname "*.cpp" -o -iname "*.h" \) -type f -print0 | xargs -0 grep --color -n "$1"

kullanın:

find-in-code "search string"
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.