Birkaç bin dosyada grep


13

Cca 26 000 dosyaları ile dizin var ve tüm bu dosyaları grep gerekir. Sorun, mümkün olduğunca hızlı ihtiyacım var, bu yüzden grep find komutundan bir dosya adını alacak ve dosyaya eşleşmeleri yazacak komut dosyası yapmak için ideal değil. "Bağımsız değişkenler listesi çok uzun" sorundan önce tüm bu dosyalarda grep crep 2 dakika sürdü. Bunu nasıl yapacağınız hakkında bir fikriniz var mı? edit: her zaman yeni dosyalar yapan bir komut dosyası vardır, bu nedenle tüm dosyaları farklı dizinlere koymak mümkün değildir.


1
or findile kullanınxargsgrep -R
Eddy_Em

İyi çalışıyor, ama 10 dakika sürüyor ...
user2778979

Yanıtlar:


19

İle find:

cd /the/dir
find . -type f -exec grep pattern {} +

( -type fyalnızca normal dosyalarda arama yapmaktır ( normal dosyaları işaret etseler bile sembolik bağlantılar hariç). Dizinler dışında herhangi bir dosya türünde arama yapmak istiyorsanız (ancak fifos veya / dev / zero gibi bazı dosya türlerine dikkat edin) genellikle okumak istemezseniz) -type fGNU'ya özel değiştirin ! -xtype d( symlink çözümlemesinden sonra -xtype dtür dizini dosyaları için eşleşir ).

GNU ile grep:

grep -r pattern /the/dir

(ancak GNU grep'in yeni bir sürümüne sahip değilseniz, dizinlere inerken sembolik bağlantıları izleyeceğini unutmayın). Bir -D readseçenek eklemediğiniz sürece normal olmayan dosyalar aranmaz . GNU'nun son sürümleri grepyine de sembolik bağlantılarda arama yapmayacaktır.

GNU'nun çok eski sürümleri findstandart {} +sözdizimini desteklemedi , ancak orada standart dışı kullanabilirsiniz:

cd /the/dir &&
  find . -type f -print0 | xargs -r0 grep pattern

Performansların G / Ç'ye bağlı olması muhtemeldir. Arama yapmanın tam zamanı, depolama alanındaki tüm verileri okumak için gereken zamandır.

Veriler yedekli bir disk dizisindeyse, aynı anda birkaç dosyayı okumak performansı artırabilir (ve aksi takdirde bozulabilir). Performanslar G / Ç'ye bağlı değilse (örneğin tüm veriler önbellekte olduğundan) ve birden fazla CPU'nuz varsa, eşzamanlı grepsda yardımcı olabilir. Sen GNU ile yapabilirsiniz xargs'ın -Pseçeneği.

Örneğin, veriler 3 sürücülü bir RAID1 dizisindeyse veya veriler önbellekte bulunuyorsa ve zamanları yedeklenecek 3 CPU'nuz varsa:

cd /the/dir &&
  find . -type f -print0 | xargs -n1000 -r0P3 grep pattern

(Burada kullanarak -n1000yeni yumurtlamaya grepbir anda paralel çalışan en fazla 3, her 1000 dosyaları).

Bununla birlikte, çıktısı grepyeniden yönlendirilirse, 3 grepişlemden hatalı serpiştirilmiş çıktı elde edeceğinizi unutmayın; bu durumda şu şekilde çalıştırmak isteyebilirsiniz:

find . -type f -print0 | stdbuf -oL xargs -n1000 -r0P3 grep pattern

(yeni bir GNU veya FreeBSD sisteminde) veya --line-bufferedGNU seçeneğini kullanın grep.

Eğer patternsabit bir dize, ekleme -Fseçeneği konularda artırabilir.

Çok baytlı karakter verisi değilse veya bu desenin eşleşmesi için verilerin çok baytlı karakter olup olmadığı önemli değildir, o zaman:

cd /the/dir &&
  LC_ALL=C grep -r pattern .

performansı önemli ölçüde artırabilir.

Bu tür aramaları sık sık yaparsanız, oradaki birçok arama motorundan birini kullanarak verilerinizi dizine eklemek isteyebilirsiniz.


3

26000 dosya tek bir dizinde çoğu dosya sistemi için çok fazladır. Muhtemelen bu büyük dizini okuyarak zamanın önemli bir kısmı alınır. Her birini yalnızca birkaç yüz dosyayla daha küçük dizinlere bölmeyi düşünün.

findYanlış yapmadığınız sürece arama kötü performansı açıklayamaz. Bu, bir dizinde gezinmenin ve çok uzun bir komut satırı yürütme girişiminde bulunmamanızı sağlamanın hızlı bir yoludur. -exec grep PATTERN {} +Komut çağırma başına olabildiğince çok dosya paketleyip kullandığınızdan , dosya başına bir kez -exec grep PATTERN {} \;yürüttüğünüzden emin olun grep: komutu dosya başına bir kez yürütmenin çok daha yavaş olması muhtemeldir.


Teşekkürler, ben bu konuda bir şey google ve muhtemelen ben onu bölmek. Tam olarak ne yazdığınızı yaptım ve sadece
grep'ten

Gilles, 100 dizinde dağıtılan 26.000 dosyaya kıyasla bir dizindeki 26.000 dosya için performansın önemli ölçüde farklı olacağını mı söylüyorsunuz?
user001

1
@ user001 Evet. Ne kadar farklı oldukları dosya sistemine ve muhtemelen temeldeki depolamaya bağlıdır, ancak herhangi bir dosya sisteminin tek bir dizindeki 26000 dosyaya kıyasla 100 dizinin her birinde 260 dosya ile ölçülebilir şekilde daha hızlı olmasını beklerim.
Gilles 'SO- kötü olmayı bırak'

Açıklama için teşekkürler. Bu noktada tutarsızlığın temelini anlamak için bir takip sorusu sordum .
user001

0

TÜM dosyaları birden çok kez grep gerekiyorsa (dediğin gibi, bir komut dosyası çalıştırma) Koç disklerine bakmanızı, tüm dosyaları oraya kopyalamanızı ve daha sonra dosyaları birden çok kez grep etmenizi öneririm, bu, aramanızı bir faktörle hızlandırır. en az 100x.

Sadece yeterli koza ihtiyacınız var. Aksi takdirde, dosyaları endekslemeye bakmalısınız, örn. lucene ya da nosql veri tabanına koyduktan sonra bunun üzerine sorguları çalıştırıyoruz.


Başka bir yerde belirtildiği gibi, bu, bir çalıştırmak için çok fazla dosya olduğu gerçeğine yardımcı olmaz grep. Ayrıca, "her zaman yeni dosyalar üreten bir komut dosyası var, bu yüzden tüm dosyaları farklı dizinlere koymak mümkün değil."
Jeff Schaller

-2

Dizindeki tüm dosyalar

grep 'search string' *

özyineli olarak

grep -R 'search string' *

-1'i hazırlamaya özen gösterilsin mi?
Markus

4
Ben aşağı itmedim, ama seninle birkaç sorun var: OP bir "arg listeden çok uzun" bahsetti, ilk senin düzeltmek olmaz ve muhtemelen OP daha önce ne yaptığını. İkincisi de bu konuda yardımcı olmuyor ( .yerine kullanmış olsaydınız yardımcı olurdu *). *nokta dosyalarını hariç tutar (yinelenen dizinlerdeki dosyaları değil, -R ile olsa da). -R yerine -r GNU grep'in son sürümlerinde bile sembolik bağlantıları takip eder. Ayrıca, geçerli dizindeki adı ile başlayan dosyalarla ilgili bir sorun -
yaşarsınız
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.