Özyineli olarak nasıl grep olurum?


1682

grepTüm dizinleri ve alt dizinleri özyinelemeli olarak nasıl yaparım ?

find . | xargs grep "texthere" *

110
@ TC1 Üzücü olan şey, grep'in soruyu cevaplayabilmesidir (en azından GNU grep): grep --help | grep özyinelemeli
Frank Schmitt

7
Özyinelemeli arama yapmak için sık sık grep kullandığınızı fark ederseniz (özellikle el ile çok fazla dosya / dizin istisnası yaparsanız) ack (çok programcı dostu bir grep alternatifi) yararlı bulabilirsiniz.
Nick McCurdy

19
Aslında işte kullandığım Solaris kutusunda ne -r ne de - yinelenen çalışma. Ve grep için man sayfa özyinelemeli bir şeyden bahsetmiyor. Ben bulmak için başvurmak zorunda kaldı ve kendimi xargs.
Ben

8
ag bunu yapmanın en sevdiğim yoludur github.com/ggreer/the_silver_searcher
dranxo

1
grep -rin xlsx *.plRedhat Linux'ta benim için çalışmıyor. "Eşleşme yok" hatası alıyorum.
Bulrush

Yanıtlar:


2507
grep -r "texthere" .

İlk parametre aranacak normal ifadeyi temsil ederken, ikinci parametre aranması gereken dizini temsil eder. Bu durumda, .geçerli dizin anlamına gelir.

Not: Bu GNU grep için geçerlidir ve Solaris gibi bazı platformlarda, eski uygulamanın aksine GNU grep'i özellikle kullanmanız gerekir. Solaris için bu ggrepkomuttur.


39
Not: "grep -r" yalnızca daha yeni grepslerde çalışır. AIX 5.3Örneğin gelen grep üzerinde çalışmaz .
Gizli

110
Sembolleri takip etmek için grep -R kullanın.
Eloff

53
"-İ" nin büyük / küçük harfe duyarlı olmadığını ve "-n" ifadesinin eşleşen her sonuç için satır numarasını içerdiğini bilmekte fayda vardır.
Sadegh

24
Ayrıca bilmek iyi, eğer sadece bir regex değil, sabit bir dize arıyorsanız, -F seçeneğini kullanın. regex ayrıştırıcısını çağırmayarak zaman scads kurtaracak. çok sayıda dosya arıyorsanız çok kullanışlı.
Jeff

6
takma ad rgrep = 'grep -r'
totten

679

İstediğiniz dosyanın uzantısını veya desenini biliyorsanız, başka bir yöntem --includeseçeneği kullanmaktır :

grep -r --include "*.txt" texthere .

Hariç tutulacak dosyalardan da bahsedebilirsiniz --exclude.

Ag

Sık sık kod içinde arama yaparsanız, Ag (The Silver Searcher) grep'e çok daha hızlı bir alternatiftir, bu da kod aramak için özelleştirilmiştir. Örneğin, varsayılan olarak özyinelemeli ve listelenen dosyaları ve dizinleri otomatik olarak yok sayar .gitignore, bu nedenle grep veya bulmak için aynı hantal dışlama seçeneklerini geçmeye devam etmeniz gerekmez.


3
Linux ve Cygwin ile gelen grep ile harika çalışıyor, ancak AIX ile gelen ile değil.
Withheld

1
@KrzysztofWolny: `` =Ubuntu'da iyi çalışıyor. Not: bunun gergin bir alan olması gerekiyordu, ancak SO işaretleme ayrıştırıcısı başarısız oldu.
Dan Dascalescu

4
@DanDascalescu Ben Ag için grepdeğil, sadece biliyorsun) için seçildi :)
Bernhard

1
Özyinelemeli arama yaparken bir dizini hariç tutma seçeneğimiz var mı?
Tom Taylor

Windows cygwin çift ​​tırnak seviyor--include "*.txt" --include "*.TXT"
Bob Stein

127

Ayrıca:

find ./ -type f -print0 | xargs -0 grep "foo"

ama grep -rdaha iyi bir cevaptır.


14
Veya dosya adlarındaki boşluklar hakkında endişelenmek istemiyorsanız, find . -type f -exec grep "foo" '{}' \;desteklenen yerlerde iyi çalışır.
Edd Steel

4
Grep için xargs üzerinden bulmaya gidecekseniz VE sadece sabit bir dize arıyorsanız (yani, normal ifade değil), grep -F seçeneğini çağırmaktan faydalanabilirsiniz, bu nedenle grep normal ifade motorunu yüklemez her çağırma için. Çok fazla dosya varsa, çok daha hızlı olacaktır.
Jeff

2
bulmak. -tip f -exec grep -Hu "foo" {} \; dosya adını verdiği için kullandığım şey bu.
Wes


1
find ./ -type f -print0 | xargs -0 grep "foo"
aehlke

118

Şimdi her zaman kullanıyorum (Windows'ta GoW - Gnu ile Windows'ta bile ):

grep --include="*.xxx" -nRHI "my Text to grep" *

Bu, aşağıdaki seçenekleri içerir:

--include=PATTERN

Yalnızca dosya eşleşmesini arayan dizinlerdeki yineleme PATTERN.

-n, --line-number

Çıktının her satırına, girdi dosyasındaki satır numarası ile önek ekleyin.

(Not: phuclv ekler yorumlarda -nböylece başarımı ciddi çok azalır bu seçeneği atlamak isteyebilirsiniz, böylece)

-R, -r, --recursive

Her dizinin altındaki tüm dosyaları özyinelemeli olarak okuyun; bu -d recurseseçenekle eşdeğerdir .

-H, --with-filename

Her eşleşme için dosya adını yazdırın.

-I     

İkili bir dosyayı, eşleşen veri içermiyormuş gibi işleyin;
bu --binary-files=without-matchseçenekle eşdeğerdir .

Büyük / küçük harfe duyarlı olmayan sonuçlar istiyorsanız ' i' ( -nRHIi) ekleyebilirim .

Alabilirim:

/home/vonc/gitpoc/passenger/gitlist/github #grep --include="*.php" -nRHI "hidden" *
src/GitList/Application.php:43:            'git.hidden'      => $config->get('git', 'hidden') ? $config->get('git', 'hidden') : array(),
src/GitList/Provider/GitServiceProvider.php:21:            $options['hidden'] = $app['git.hidden'];
tests/InterfaceTest.php:32:        $options['hidden'] = array(self::$tmpdir . '/hiddenrepo');
vendor/klaussilveira/gitter/lib/Gitter/Client.php:20:    protected $hidden;
vendor/klaussilveira/gitter/lib/Gitter/Client.php:170:     * Get hidden repository list
vendor/klaussilveira/gitter/lib/Gitter/Client.php:176:        return $this->hidden;
...

Gow umut verici görünüyor - kullandığım GNU Windows yardımcı programlarından daha yeni. Şimdi deniyorum ...
Radim Cernej

buradaki son karakterin * anlamı nedir?
lorniper

2
@lorniper, kabuğun geçerli dizininizdeki tüm dosya ve klasörleri seçmesini sağlayarak grep'i bu dosyalara ve ( -Rseçenek nedeniyle özyineli olarak ) klasörlere uygular .
VonC

2
@lorniper Noy tam olarak: *veya .bir glob paternidir (kabuk tarafından yorumlanır): unix.stackexchange.com/a/64695/7490 . ' .' nokta dosyaları veya nokta klasörleri de seçecektir (örneğin .git/)
VonC

Daha önce her zaman kullandım grep -rnIama sonra -nperformansı çok düşürdüğünü öğrendim, bu yüzden gerçekten gerektiğinde kullanıyorum ve normalde kullanacağım-rI
phuclv

25

POSIX sistemlerinde, için -rparametre bulamazsınız grepve grep -rn "stuff" .çalışmazsınız, ancak findkomutu kullanırsanız :

find . -type f -exec grep -n "stuff" {} \; -print

Tarafından kabul edilen Solarisve HP-UX.


anlamı ne {} \; baskı?
user1169587

3
In -execseçeneği - sembol {}şu anda tarafından bulunan dosya adına bir referanstır find(bulduğumuz isimle bir şeyler yapmak olduğunu) aracı, aynı zamanda -execseçenek ile sonlandırılmalıdır ;bu her çünkü (exec komutların biten işaretine) sembolü, ama Bu sembol bir kabuk kaçmak gerekir .. ve son olarak -printseçeneği findekranda bulunan dosya adlarını yazdırmak için aracı sağlar .
kale

19

globbing **

grep -rÇalışmaları kullanmak , ancak özellikle büyük klasörlerde aşırıya kaçabilir.

Daha pratik kullanım için, globbing sözdizimini ( **) kullanan sözdizimi :

grep "texthere" **/*.txt

yalnızca desen seçili desene sahip belirli dosyaları açar. Bash +4 veya zsh gibi desteklenen mermiler için çalışır .

Bu özelliği etkinleştirmek için, çalıştırın: shopt -s globstar.

Ayrıca bkz: Linux'ta belirli metin içeren tüm dosyaları nasıl bulurum?

git grep

Git sürüm kontrolü altındaki projeler için şunu kullanın:

git grep "pattern"

çok daha hızlı.

ripgrep

Daha büyük projeler için, ripgrepdosyaları en hızlı şekilde selamlayan, dosyaları varsayılan olarak özyinelemeli:

rg "pattern" .

Rust'un arama işlemini çok hızlı hale getirmek için sonlu otomata, SIMD ve agresif gerçek optimizasyonları kullanan normal regex motorunun üzerine inşa edilmiştir . Ayrıntılı analizi buradan kontrol edin .


3
Git grep öneri için teşekkürler - çok yararlı ve bu konuda bilmiyordum!
Basya

2
Ripple önerisi için teşekkürler. Çok daha hızlı.
Soğuk Olacak Ne

11

Aşağıdaki komutu fileskullanarak pathyinelemeli olarak içeren adını bulmak stringiçin aşağıdaki komutu kullanın UNIX:

find . | xargs grep "searched-string"

için Linux:

grep -r "searched-string" .

UNIXsunucuda bir dosya bul

find . -type f -name file_name

LINUX sunucusunda bir dosya bulma

find . -name file_name

11

sadece dosya adları da yararlı olabilir

grep -r -l "foo" .

10

Sembolik bağlantıları değil, yalnızca gerçek dizinleri takip etmek istiyorsanız,

grep -r "thingToBeFound" directory

Sembolik bağlantıları ve gerçek dizinleri takip etmek istiyorsanız (sonsuz özyinelemeye dikkat edin),

grep -R "thing to be found" directory

Tekrar tekrar grep yapmaya çalıştığınız için, aşağıdaki seçenekler de sizin için yararlı olabilir:

-H: outputs the filename with the line

-n: outputs the line number in the file

Geçerli dizinde veya herhangi bir alt dizinde Darth Vader içeren tüm dosyaları bulmak ve dosya adını ve satır numarasını yakalamak istiyorsanız, ancak özyinelemenin sembolik bağlantıları izlemesini istemiyorsanız, komut

grep -rnH "Darth Vader" .

Eğer dizinde cat kelimesinin tüm sözlerini bulmak istiyorsanız

/home/adam/Desktop/TomAndJerry 

ve şu anda dizindesiniz

/home/adam/Desktop/WorldDominationPlot

ve "kediler" dizesinin herhangi bir örneğinin dosya adını yakalamak istemiyorsanız ve özyinelemeyi bulursa sembolik bağlantıları izlemesini istiyorsanız, aşağıdakilerden birini çalıştırabilirsiniz

grep -RH "cats" ../TomAndJerry                   #relative directory

grep -RH "cats" /home/adam/Desktop/TomAndJerry   #absolute directory

Kaynak:

"grep --help" çalıştırıyor

Bu cevabı okuyan ve onlara referansımla karışan herkes için sembolik bağlantılara kısa bir giriş: https://www.nixtutor.com/freebsd/understanding-symbolic-links/


Mükemmel cevap. Ekstra anahtarlar (-rnh) çok faydalıdır, bu yüzden onları önerdiğiniz için teşekkürler.
semtex41

8

ag bunu yapmanın en sevdiğim yoludur github.com/ggreer/the_silver_searcher . Temelde ack ile aynı şey ama birkaç optimizasyon ile.

İşte kısa bir ölçüt. Her testten önce önbelleği temizlerim (cf /ubuntu/155768/how-do-i-clean-or-disable-the-memory-cache )

ryan@3G08$ sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
3
ryan@3G08$ time grep -r "hey ya" .

real    0m9.458s
user    0m0.368s
sys 0m3.788s
ryan@3G08:$ sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
3
ryan@3G08$ time ack-grep "hey ya" .

real    0m6.296s
user    0m0.716s
sys 0m1.056s
ryan@3G08$ sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
3
ryan@3G08$ time ag "hey ya" .

real    0m5.641s
user    0m0.356s
sys 0m3.444s
ryan@3G08$ time ag "hey ya" . #test without first clearing cache

real    0m0.154s
user    0m0.224s
sys 0m0.172s


6

Bir dizin yapısındaki tüm dosyalarda belirli bir içerik arıyorsanız, findne yaptığınızı daha açık olduğu için kullanabilirsiniz :

find -type f -exec grep -l "texthere" {} +

Not o -l(L downcase) metin içeren dosyanın adını gösterir. Eşleşmenin kendisini yazdırmak istiyorsanız bunu kaldırın. Veya -Hdosyayı eşleşmeyle birlikte almak için kullanın . Hep birlikte, diğer alternatifler:

find -type f -exec grep -Hn "texthere" {} +

Nerede -nsatır numarasını yazdırır.


2
Sadece olduğu için Yukarı-olarak findher iki önlemek gereksiz kullanımına çözüm xargsve kullanımı +yerine \;sahip -exec, böylece gereksiz işlem başlattı ton kaçınarak. :-)
ShadowRanger

6

Şu anki makinemdeki durumum için çalışan (Windows 7'de git bash):

find ./ -type f -iname "*.cs" -print0 | xargs -0 grep "content pattern"

Boşluklu yollar için -print0 ve -0 öğelerini daima unuturum.

EDIT: Tercih ettiğim araç artık bunun yerine ripgrep: https://github.com/BurntSushi/ripgrep/releases . Gerçekten hızlı ve daha iyi varsayılanlara sahip (varsayılan olarak özyinelemeli gibi). Orijinal cevabımla aynı örnek ama ripgrep kullanma:rg -g "*.cs" "content pattern"


4

grep -r "texthere" . (sondaki ihbar süresi)

(^ kredi: https://stackoverflow.com/a/1987928/1438029 )


Açıklama:

grep -r "texthere" /( tüm dizinleri ve alt dizinleri özyinelemeli olarak grep )

grep -r "texthere" .( bu dizinleri ve alt dizinleri özyinelemeli olarak grep )

grep özyinelemeli

grep [options] PATTERN [FILE...]

[Seçenekler]

-R, -r, --recursive

Her dizinin altındaki tüm dosyaları yinelemeli olarak okuyun.

Bu, -d recurseveya --directories=recurseseçeneğine eşdeğerdir .

http://linuxcommand.org/man_pages/grep1.html

grep yardımı

$ grep --help

$ grep --help |grep recursive
  -r, --recursive           like --directories=recurse
  -R, --dereference-recursive

Alternatifler

ack( http://beyondgrep.com/ )

ag( http://github.com/ggreer/the_silver_searcher )


4

2018'de kullanmak istiyorsunuz ripgrepveya the-silver-searcheralternatiflerden çok daha hızlı oldukları için.

İşte 336 birinci seviye alt dizini olan bir dizin:

% find . -maxdepth 1 -type d | wc -l
     336

% time rg -w aggs -g '*.py'
...
rg -w aggs -g '*.py'  1.24s user 2.23s system 283% cpu 1.222 total

% time ag -w aggs -G '.*py$'
...
ag -w aggs -G '.*py$'  2.71s user 1.55s system 116% cpu 3.651 total

% time find ./ -type f -name '*.py' | xargs grep -w aggs
...
find ./ -type f -name '*.py'  1.34s user 5.68s system 32% cpu 21.329 total
xargs grep -w aggs  6.65s user 0.49s system 32% cpu 22.164 total

OSX, bu yükler ripgrep: brew install ripgrep. Bu yükler silver-searcher: brew install the_silver_searcher.


Bunu sık sık yapmanız gerekiyorsa hız önemlidir, ancak çoğumuz bunu yılda sadece birkaç kez yapıyoruz. En son spiffy üçüncü taraf juju tool du jour'u yüklemek çok fazla ve 1978'den bu yana çok fazla değişmeyen çözümler ne olursa olsun bilmek iyi.
tripleee

Bir programcının kaynak ağacında yılda sadece birkaç kez metin araması son derece mantıklı değil. Ancak kullanılabilirlik açısından bile rg, sıfırdan tekrarlayan bir grep komutunun birlikte kaldırılması üzerinde önemli bir kenarı vardır. Kullanımı rg: rg foo. Unix araçları kullanma: find . | xargs grep foo. Ve dosyalarınızdan herhangi birinin içinde bir alıntı varsa, kullanmanız gerekir find . -print0 | xargs -0 grep foo. Bunu yılda birkaç kez kullanırsanız hatırlayacak mısınız?
hughdbrown

1
find . -type f -exec grep 'regex' {} +Bu araçları herhangi bir düzenlilikle kullanırsanız hangisinin hatırlanması gerçekten kolay olduğunu unutuyorsunuz . Ama muhtemelen çalışmalıdır ctagsveya etagssık şeyler bulmak gerekiyorsa kaynak ağacı oldu Neyse üzerinde.
üçlü

Ripgrep kullanıyorum ve harika. Ancak gümüş araştırmacı programcılar için harika. +1
Matt

3

IBM AIX Sunucumda (işletim sistemi sürümü: AIX 5.2) şunları kullanın:

find ./ -type f -print -exec grep -n -i "stringYouWannaFind" {} \; 

bu, dosyadaki yolu / dosya adını ve göreli satır numarasını aşağıdaki gibi yazdırır:

./inc/xxxx_x.h

2865: / ** Açıklama: stringYouWannaFind * /

neyse, benim için çalışıyor :)


3

Aşağıda, Stringözyinelemeli bir ortamda Unixve Linuxortamda arama komutu verilmiştir .

için UNIXkomutun geçerli:

find . -name "string to be searched" -exec grep "text" "{}" \;

için Linuxkomutun geçerli:

grep -r "string to be searched" .

2

Mevcut bayrakların bir listesi için:

grep --help 

Geçerli dizindeki normal ifade metninin tüm eşleşmelerini karşılık gelen satır numarasıyla döndürür :

grep -rn "texthere" .

Kök dizinden başlayarak karşılık gelen satır numarası ve yoksayma durumu ile birlikte texthere için tüm eşleşmeleri döndürür :

grep -rni "texthere" /

Burada kullanılan bayraklar:

  • -r özyinelemeli
  • -n çıktı ile satır numarasını yazdır
  • -i davayı yoksay

1

Sanırım yazmaya çalıştığın şey bu

grep myText $(find .)

ve grep hit dosyalarını bulmak istiyorsanız bu başka bir şey olabilir

grep myText $(find .) | cut -d : -f 1 | sort | uniq

Çok sezgisel: örneğin: grep -i acc $ (find. -Name "execution *. *")
Yu Shen

1

İki sentimi buraya atıyorum. Diğerlerinin de belirttiği gibi grep -r her platformda çalışmaz. Bu aptalca gelebilir ama ben hep git kullanıyorum.

git grep "texthere"

Dizin sahnelenmemiş olsa bile, ben sadece sahne ve git grep kullanın.


0

Bunu not et find . -type f | xargs grep whateverBulma ile eşleşen çok fazla dosya olduğunda, birçok çözümün "Uzun süre için bağımsız değişken listesi" hatalarında çalışacağını .

En iyi bahis, grep -rancak bu mevcut değilse, find . -type f -exec grep -H whatever {} \;bunun yerine kullanın.


Ha? xargs"Bağımsız değişken listesi çok uzun" sorunu için özellikle geçici bir çözümdür.
tripleee

2
Hayır - xargs özellikle bir argüman borusunu arglist'e dönüştürmek içindir, ancak evet, -s ve / veya -L ile birlikte kullanıldığında modern xargs'ın birden fazla komut çağrısına girerek çok uzun arglistlerle başa çıkabileceği doğrudur, ancak varsayılan olarak bu şekilde yapılandırılmaz (ve yukarıdaki yanıtların hiçbirinde yoktu). Örnek olarak:find . -type f | xargs -L 100 grep whatever
m.thome

Hangi platformda olurdu? POSIXxargs , bu davranışı kutudan çıkarmak üzere standartlaştırılmıştır. "Yardımcı xargsprogram, komut satırı uzunluğunu, komut satırı çağrıldığında, birleştirilmiş argüman ve ortam listeleri ... {ARG_MAX} -2048 baytı aşmayacak şekilde sınırlayacaktır."
tripleee

Hm. Gnu belgeleri bu temelde posix'ten daha az açık olsa da ve artık bu ifadeyi yapmama neden olan makineye erişemiyorum, ancak mevcut herhangi bir uygulamadaki orijinal yorumumu doğrulayamıyorum. Özyinelemeli grep, elbette, hala mevcutsa tercih edilir, ancak xargs reçetesinden kaçınmak için çok az neden vardır (grep'in nihai çağrısının sadece tek bir dosya adından geçmesini önlemek için grep için -H kullanın).
m.thome

0

Sadece eğlence için, @christangrant cevabı yazmak için çok fazla ise * .txt dosyalarının hızlı ve kirli bir araması :-)

grep -r texthere .|grep .txt


0

Aşağıda, belirli bir klasörün ($ 1) tüm alt klasörlerini (ve 1 $) grepbelirli dizede ($ 3) aramaları kullanarak ($ ​​2) yinelemeli (bash ve sh ile hafifçe test edilmiştir) işlev vardır :

$ cat script.sh
#!/bin/sh

cd "$1"

loop () {
    for i in *
    do
        if [ -d "$i" ]
        then
            # echo entering "$i"
            cd "$i"
            loop "$1" "$2"
        fi
    done

    if [ -f "$1" ]
    then
        grep -l "$2" "$PWD/$1"
    fi

    cd ..
}

loop "$2" "$3"

Çalıştırma ve örnek bir çıktı:

$ sh script start_folder filename search_string
/home/james/start_folder/dir2/filename

-2
The syntax is:
cd /path/to/dir
grep -r <"serch_word name"> .

7
Bu, diğer cevaplara fazla bir şey katmaz
Mel
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.