Belirli dosyalar arasında grep yapmamak için grep --exclude / - include sözdizimini kullanın


780

foo=Bir dizin ağacındaki metin dosyalarında dize arıyorum . Ortak bir Linux makinesinde, bash kabuğum var:

grep -ircl "foo=" *

Dizinlerde de "foo =" ile eşleşen birçok ikili dosya bulunmaktadır. Bu sonuçlar alakalı olmadığından ve aramayı yavaşlattığından, grep'in bu dosyaları aramayı atlamasını istiyorum (çoğunlukla JPEG ve PNG görüntüleri). Bunu nasıl yaparım?

--exclude=PATTERNVe --include=PATTERNseçenekleri olduğunu biliyorum , ama desen formatı nedir? Grep'in man sayfası şöyle diyor:

--include=PATTERN     Recurse in directories only searching file matching PATTERN.
--exclude=PATTERN     Recurse in directories skip file matching PATTERN.

Grep arama, dahil etme , grep dahil etme , grep hariç tutma ve varyantlar alakalı bir şey bulamadı

Sadece belirli dosyalarda daha iyi bir şekilde selam vermenin daha iyi bir yolu varsa, ben bunun için varım; Sorun yaratan dosyaları taşımak bir seçenek değildir. Sadece belirli dizinleri arayamıyorum (dizin yapısı her yerde her şey ile büyük bir karmaşa). Ayrıca, hiçbir şey yükleyemiyorum, bu yüzden ortak araçlarla ( grep veya önerilen bulma gibi ) yapmak zorundayım .


13
Sadece FYI, kullanılan argümanlar: -c dosyadaki eşleşmeleri saymak -i case-insensitive -l sadece eşleşen dosyaları göster -r özyinelemeli
Piskvor

68
Svn --exclude-dir=.svn
dirs'i

25
İnsanların bilmesi gereken birkaç bilgiçlik noktası: 1. Burada globun etrafında tırnak bulunmadığına dikkat edin: --exclude = ' . {Png, jpg}' çalışmıyor (en azından GNU grep sürümümde) çünkü grep globlarında {} desteklemiyor. Yukarıdaki '--exclude = .png --exclude = *. Jpg' (cwd'de hiçbir dosya eşleşmediğini varsayarsak - normalde '--exclude =' ile dosya adlarını başlatmamanız olası değildir) grep gayet iyi seviyor. 2. --exclude, bir GNU uzantısıdır ve POSIX'in grep tanımının bir parçası değildir, bu nedenle komut dosyaları yazarsanız, bunların GNU olmayan sistemlerde çalışması gerekmeyeceğini unutmayın.
ijw

2
Exclude-dir kullanımına tam örnek:grep -r --exclude-dir=var "pattern" .
Tisch

Yanıtlar:


767

Kabuk globbing sözdizimini kullanın:

grep pattern -r --include=\*.{cpp,h} rootdir

İçin sözdizimi --excludeaynıdır.

Yıldızın kabuk tarafından genişletilmesini önlemek için bir ters eğik çizgiyle kaçıldığını unutmayın (tırnak işareti de --include="*.{cpp,h}"aynı şekilde işe yarayacaktır). Aksi takdirde, geçerli çalışma dizininde desenle eşleşen herhangi bir dosyanız varsa, komut satırı grep pattern -r --include=foo.cpp --include=bar.h rootdir, yalnızca adlı dosyaları arayacak foo.cppve bar.hbüyük olasılıkla istediğinizi olmayan bir şeye genişleyecektir .


8
Neden bilmiyorum, ama böyle dahil desen alıntı vardı:grep pattern -r --include="*.{cpp,h}" rootdir
topek

6
@topek: İyi bir nokta - geçerli dizininizde herhangi bir .cpp / .h dosyanız varsa, kabuk grep'i çağırmadan önce glob'u genişletecek, böylece grep pattern -r --include=foo.cpp --include=bar.h rootdirsadece dosyaları arayacak bir komut satırı ile sonuçlanacaksınız. adlı foo.cppveya bar.h. Geçerli dizindeki glob ile eşleşen herhangi bir dosyanız yoksa, kabuk glob üzerinde grep'e geçer ve doğru yorumlanır.
Adam Rosenfield

6
Glob'un sadece dosya adıyla eşleşmeye alışık olduğunu fark ettim. Bir dizinin tamamını hariç tutmak için bir --exclude-dirseçeneğe ihtiyaç vardır . Yine de aynı kurallar geçerlidir. Bir yolla değil, yalnızca dizin dosya adı eşleşir.
Krzysztof Jabłoński

3
--includesonra işe yaramıyor gibi görünüyor --exclude. Ben aliasuzun bir liste ile bir grep var --excludeve --exclude-dirkod arama, kütüphaneler ve takas dosyaları ve şeyler göz ardı etmek için kullandığım dışında, denemek bile mantıklı olmadığını düşünüyorum . Bunun grep -r --exclude='*.foo' --include='*.bar'işe yarayacağını umuyordum , bu yüzden sadece benim aliasiçin sınırlayabilirim --include='*.bar', ancak görmezden geliyor --includeve bir .foo dosyası olmayan her şeyi içeriyor gibi görünüyor . Sırasını --includeve --excludeişlerini değiştirmek, ama ne yazık ki, bu benim için yararlı değil alias.
Michael Scheper

1
bunun için kurallar almak üzere birinin aklını nasıl okuyabiliriz PATTERN. Yarım saat orada ne bekledikleri hakkında bir açıklama bulamıyorum
Arkady

221

Sadece ikili dosyaları atlamak istiyorsanız, -I(büyük harf i) seçeneğine bakmanızı öneririm . İkili dosyaları yok sayar. Düzenli olarak aşağıdaki komutu kullanıyorum:

grep -rI --exclude-dir="\.svn" "pattern" *

Yinelemeli olarak arama yapar, ikili dosyaları yok sayar ve Subversion gizli klasörlerinin içine bakmak istemez. Ben iş yerinde benim kutusu üzerinde "grepsvn" olarak takma var.


1
Teşekkürler, karşılaştığım diğer senaryolar için çok faydalı.
Piskvor binadan ayrıldı

25
--exclude-dirher yerde mevcut değildir. GNU grep 2.5.1 ile çalışan RH kutumda yok.
gcb

Kullanılamadığında ne kullanacağınıza dair herhangi bir öneriniz var --exclude-dirmı? Tüm girişimlerimde, --excludefaturaya uygun görünmüyor.
JMTyler

GNU'dan her zaman en son grep kaynağını indirebilir ve 'configure; Yapmak; sudo make install 'adlı öğeyi seçin. Mac veya daha eski bir Linunx dağıtımında yaptığım ilk şeylerden biri bu.
Jonathan Hartley

3
Tam olarak ihtiyacım olan şey. Aslında git kullanıyorum. Yani --exclude-dir="\.git",. :-)
Ionică Bizău

66

Lütfen tam olarak bu durumlar için tasarlanmış olan ack'a bir göz atın . Örneğiniz

grep -ircl --exclude=*.{png,jpg} "foo=" *

ack ile yapılır

ack -icl "foo="

çünkü ack hiçbir zaman varsayılan olarak ikili dosyalara bakmaz ve -r varsayılan olarak açıktır. Ve sadece CPP ve H dosyalarını istiyorsanız,

ack -icl --cpp "foo="

Güzel görünüyor, bir dahaki sefere bağımsız Perl sürümünü deneyecek, teşekkürler.
Piskvor

5
İyi arama, artık ack olmadan yaşayamam.
Şans

1
stackoverflow.com/questions/667471/… - Bu, grep'i çalıştırdığınız yerse, pencerelerde ack almanıza izin verecektir.
TamusJRoyce

@Chance Belki silversearcher-ag , sadece apt-getUbuntu'da :)
Justme0

ile karıştırılmamalıdırawk
jasonleonhard

35

grep 2.5.3 istediğiniz şekilde çalışacak --exclude-dir parametresini tanıttı.

grep -rI --exclude-dir=\.svn PATTERN .

Ayrıca bir ortam değişkeni de ayarlayabilirsiniz: GREP_OPTIONS = "- exclude-dir = .svn"

Ben ikinci edeceğiz Andy'nin için oy ack olsa iyi olur.


7
Tam sürüm numarasını belirtmek için +1; Grep 2.5.1 var ve exclude-dir seçeneği mevcut değil
James

25

Bunu uzun bir süre sonra buldum, birden fazla ekleme ve hariç tutma ekleyebilirsiniz:

grep "z-index" . --include=*.js --exclude=*js/lib/* --exclude=*.min.js

5
Bunları aşağıdaki gibi bir listede birleştirmek daha iyidir: --exclude = {pattern1, pattern2, pattern3}
Yasser Sinjab

12

Önerilen komut:

grep -Ir --exclude="*\.svn*" "pattern" *

kavramsal olarak yanlıştır, çünkü --exc temel üzerinde çalışır. Başka bir deyişle, yalnızca geçerli dizindeki .svn'yi atlar.


3
Evet, benim için hiç işe yaramıyor. Benim için çalışan: exclude-dir = .svn
Taryn East

2
@Nicola teşekkür ederim! Bunun neden işe yaramadığı konusunda saçlarımı yırtıyorum. Söylesene, bunu sayfadan keşfetmenin bir yolu var mı? Tek söylediği şey "PATTERN" ile eşleşiyor. EDIT manpage burada açıklandığı gibi "dosya" diyor fixunix.com/unix/…
13ren

11

Grep 2.5.1'de bu satırı ~ / .bashrc veya ~ / .bash profiline eklemelisiniz

export GREP_OPTIONS="--exclude=\*.svn\*"

9

Grepping grep'in çıktısının bazen çok yardımcı olduğunu düşünüyorum:

grep -rn "foo=" . | grep -v "Binary file"

Yine de, bu aslında ikili dosyaları aramasını engellemez.


10
grep -Iİkili dosyaları atlamak için kullanabilirsiniz .
Nathan Fellman

ben de gençken ... şimdi daha iyi biliyorum ve bir sorunla karşılaştığınızda, ilk şey RTFM
gcb

grep, renk vurgularını kaldıracaktır.
Max Li

7

Kullanmaktan çekinmiyorsanız find, -pruneözelliğini beğendim :

find [directory] \
        -name "pattern_to_exclude" -prune \
     -o -name "another_pattern_to_exclude" -prune \
     -o -name "pattern_to_INCLUDE" -print0 \
| xargs -0 -I FILENAME grep -IR "pattern" FILENAME

İlk satırda, aramak istediğiniz dizini belirtirsiniz. .(geçerli dizin) geçerli bir yoldur, örneğin.

2. ve 3. hatları, kullanım günü "*.png", "*.gif", "*.jpg"ve benzeri. Bu -o -name "..." -pruneyapıların çoğunu desenleriniz kadar kullanın .

4. satırda, istediğiniz -o(veya "to" karakterini find), istediğiniz desenlere ve bunun sonuna a -printveya -print0sonunda ihtiyacınız vardır . Sadece kalıntılar budama sonra o "her şey" istiyorsanız *.gif, *.pngvb görüntüleri, daha sonra kullanmak -o -print0ve 4 satır ile bitti.

Son olarak, 5. satırda, xargssonuçta elde edilen dosyaların her birini alan ve bunları bir değişkente saklayan boru bulunur FILENAME. Sonra grep, -IRbayrakları geçer "pattern"ve sonra FILENAMEtarafından xargsbulunan dosya adları listesi haline getirmek için genişletilir find.

Özel sorunuz için ifade aşağıdaki gibi görünebilir:

find . \
     -name "*.png" -prune \
     -o -name "*.gif" -prune \
     -o -name "*.svn" -prune \
     -o -print0 | xargs -0 -I FILES grep -IR "foo=" FILES


Önereceğim bir değişiklik: -falseher birini hemen sonra -prunekullanmayı unutmak -print0veya bir tür execkomut aslında hariç tutmak istediğiniz dosyaları yazdırmaz: -name "*.png" -prune -false -o name "*.gif -prune -false...
OnlineCop

7

CentOS 6.6 / Grep 2.6.3'te şöyle kullanmak zorundayım:

grep "term" -Hnir --include \*.php --exclude-dir "*excluded_dir*"

(Aksi takdirde "=" eşit işaretinin eksikliği dikkat --include, --exclude, include-dirve --exclude-dirgöz ardı edilir)


6

git grep

Kullanım git grepperformansı ve amaçları için optimize edilmiştir belli dosyalar arasında arama yapmak.

Varsayılan olarak ikili dosyaları yok sayar ve onurlandırır .gitignore. Git yapısıyla çalışmıyorsanız, yine de geçerek kullanabilirsiniz--no-index .

Örnek sözdizimi:

git grep --no-index "some_pattern"

Daha fazla örnek için bakınız:


5

Ben bir dilettantım, ama ~ / .bash_profile'ım şöyle görünüyor:

dışa aktar GREP_OPTIONS = "- orl --exclude-dir = .svn --exclude-dir = .cache --color = auto" GREP_COLOR = '1; 32'

İki dizini hariç tutmak için --exclude-dir'i iki kez kullanmam gerektiğini unutmayın.



3

Yinelemesiz arama yaparsanız , dosya adlarıyla eşleştirmek için glop kalıplarını kullanabilirsiniz .

grep "foo" *.{html,txt}

html ve txt içerir. Yalnızca geçerli dizinde arama yapar.

Alt dizinlerde arama yapmak için:

   grep "foo" */*.{html,txt}

Alt dizinlerde:

   grep "foo" */*/*.{html,txt}

3

Dizinlerde ayrıca birçok ikili dosya vardır. Sadece belirli dizinleri arayamıyorum (dizin yapısı büyük bir karmaşa). Sadece belirli dosyalarda daha iyi selamlama yolu var mı?

ripgrep

Bu, geçerli dizininizi özyinelemeli olarak aramak için tasarlanmış en hızlı araçlardan biridir. Maksimum verimlilik için Rust'un regex motorunun üzerine inşa edilmiş Rust'da yazılmıştır . Ayrıntılı analizi buradan kontrol edin .

Böylece sadece koşabilirsiniz:

rg "some_pattern"

Senin saygı .gitignoreGizli dosyalarınıza / dizinlerinize ve ikili dosyalarınıza ve otomatik olarak atlar.

-g/ Düğmelerini kullanarak dosya ve dizinleri dahil edebilir veya hariç tutabilirsiniz --glob. Globbing kuralları globlarla eşleşir .gitignore. man rgYardım olup olmadığını kontrol edin .

Daha fazla örnek için, bkz. Grep ile belirli uzantılarla eşleşmeyen bazı dosyalar nasıl hariç tutulur?

MacOS'ta, aracılığıyla yükleyebilirsiniz brew install ripgrep.


3

bulmak ve xargs arkadaşlarınız. Bunları grep yerine --exclude yerine dosya listesine filtre uygulamak için kullanın

Gibi bir şey dene

find . -not -name '*.png' -o -type f -print | xargs grep -icl "foo="

Buna alışmanın avantajı, örneğin tüm png olmayan dosyalardaki satırları saymak için diğer kullanım durumlarına genişletilebilir olmasıdır:

find . -not -name '*.png' -o -type f -print | xargs wc -l

PNG olmayan tüm dosyaları kaldırmak için:

find . -not -name '*.png' -o -type f -print | xargs rm

vb.

Yorumlarda belirtildiği gibi, bazı dosyaların adlarında boşluklar varsa, -print0ve xargs -0yerine kullanın.


1
Bu, boşluklu dosya adlarında çalışmaz, ancak bu sorun yazdırmak yerine print0 kullanılarak ve xargs'a -0 seçeneği eklenerek kolayca çözülür.
Adam Rosenfield

2

bu komut dosyaları tüm sorunu çözmez ... Bunu daha iyi deneyin:

du -ha | grep -i -o "\./.*" | grep -v "\.svn\|another_file\|another_folder" | xargs grep -i -n "$1"

Bu komut dosyası çok daha iyidir, çünkü dizinlerin aranmasını önlemek için "gerçek" düzenli ifadeler kullanır. klasör veya dosya adlarını "\ |" ile ayırın grep -v'de

tadını çıkar! linux kabuğumda buldum! XD


2

Şuna bak.

grep --exclude="*\.svn*" -rn "foo=" * | grep -v Binary | grep -v tags

2
Yaklaşık olarak bunu başaran şeyler diğer yazılarda da ele alınmıştır; dahası, bu yanlış, çeşitli düzen seçenekleri ayarlandığında satır numaralarını ve bunun gibi şeyleri bertaraf edecek veya istenen bağlam çizgilerini hariç tutacak.
Chris Morgan

aynı anda birkaç "-v" seçeneğini nasıl kullanabilirsiniz?
yolu açın

1

--binary-files=without-matchGNU seçeneği grepde ikili dosyaları atlamak için alır. ( -IBaşka bir yerde bahsedilen anahtara eşdeğerdir .)

(Bu grep, en azından 2.5.3 sürümüne sahip olması gereken bir sürümünü gerektirebilir .)


1

tcsh .alias dosyası için uygun:

alias gisrc 'grep -I -r -i --exclude="*\.svn*" --include="*\."{mm,m,h,cc,c} \!* *'

{Mm, m, h, cc, c} bölümünün tırnak içinde OLMAMASI gerektiğini anlamak için biraz zaman aldı. ~ Keith


0

Grep'ten gelen tüm ikili sonuçları yok saymak için

grep -Ri "pattern" * | awk '{if($1 != "Binary") print $0}'

Awk kısmı tüm İkili dosya foo satırları filtreler


-2

Bunu dene:

  1. --FCurrdir .. altında " " adlı bir klasör oluşturun (veya orada " --F" olarak yeniden adlandırılan başka bir klasörü bağlayın double-minus-F.
  2. #> grep -i --exclude-dir="\-\-F" "pattern" *
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.