Grep, bir dizinde özyinelemesiz olarak tüm dosyalar üzerinde nasıl kullanılır?


34

Bir dizindeki tüm dosyalarda bir metin dizisi aramak istiyorum (ve alt dizinleri değil; -rseçeneğin bunu yaptığını biliyorum ama istediğim bu değil).

  1. Koşu

    grep "string" /path/to/dir
    

    Bunu yapabilmek gerekiyordu, okudum ama bana hata veriyor:

    grep: dir: Bir dizindir

  2. Sonra, grepbirden fazla dosya üzerinde çalışmayı denedim .

    grep "string" .bashrc .bash_aliases Mükemmel çalışıyor.

    grep "string" .bash* de amaçlandığı gibi çalışır.

    grep "string" * bana hataları veriyor:

    grep: data: Is a directory
    grep: Desktop: Is a directory
    grep: Documents: Is a directory
    grep: Downloads: Is a directory
    ...
    

Sadece hatalar yazdırılıyor, eşleşen satırları alamıyorum. Kullanmaya çalıştım-sSeçeneği ama boşuna.

Yani benim sorularım:

  1. Neden grepbir dizin üzerinde kullanamıyorum , (1) 'deki gibi ne zaman kullanmalıyım? İnternette birçok örnekte yapıldığını gördüm.
    Düzenleme : "bir dizinde grep kullanma" derken, "alt dizinleri hariç o dizindeki tüm dosyaları ara" demiştim. Bir dosya yerine bir dizine geçtiğinizde grep'in yaptığı şeyin bu olduğuna inanıyorum. Yanlış mıyım?

  2. Lütfen bana grep(2) 'deki komutların davranışını açıklayan çalışmalarına ilişkin bir açıklama yapınız .
    Düzenleme : Daha spesifik olalım. Neden jokerleri kullanarak çalışmak için .bash*ve *hatta aramasın diye aramak üzere birden fazla dosya belirtmek için kullanıyor ./*?

  3. Bir dizindeki tüm dosyaları (alt dizinlerini değil) kullanarak nasıl arayabilirim grep?


Ayrıca *, küreselleşme olarak bilinen kabuk genişletme joker karakterlerine güveniyorsunuz . Küreselleşme, .bashrcstandart gibi bir nokta ile başlayan dosya adlarını içermez . Bu dosyaları içerecek şekilde kabuk seçeneklerini ayarlayabilirsiniz, ancak ne yaptığınızı bilmiyorsanız, kendinizi biraz karışıklığa bulaştırın. Dünyayı anlamak için iyi bir rehber burada bulunabilir mywiki.wooledge.org/glob
Arronical

Neden olduğunu bilmiyorum, ama her zaman gizli dosyalara sıkışma yaptım ve her zaman işe yaradı. Herhangi bir ayar veya herhangi bir şeyi değiştirmedim. (2) 'de işaret ettiğim gibi, onunla da çalışır grep "string" .bash*.
John Red

Üzgünüm, son örneğim yanlıştı. Gizli dosyaları da arayabilir ve "bir dizindir" ifadesini kaldırarak Linux teknik olarak farklı bir dosya türü olarak görülebilir. Komut sonra olacaktır: grep "string" * .* 2>/dev/nullyagrep -s "string" * .*
Terrance

Yanıtlar:


40

Bash'de, bir glob gizli dosyalara genişlemeyecektir, bu nedenle bir dizindeki tüm dosyaları aramak istiyorsanız , gizli dosyaları .*ve gizli olmayanları belirtmeniz gerekir *.

"Bir dizin mi" hatalarından kaçınmak için kullanabilirsiniz -d skip, ancak sistemimde ayrıca bir hata iletisi grep: .gvfs: Permission denied alıyorum , bu nedenle kullanmanızı öneririm -s, bu da tüm hata iletilerini gizler.

Yani aradığınız komut şudur:

grep -s "string" * .*

Başka bir dizinde dosya arıyorsanız:

grep -s "string" /path/to/dir/{*,.*}

Başka bir seçenek de dotglobgizli dosyaları içeren bir glob yapacak kabuk seçeneğini kullanmaktır .

shopt -s dotglob
grep -s "string" *

Başka bir dizindeki dosyalar için:

grep -s "string" /path/to/dir/*

† Birisi bu hatayı almamam gerektiğini söyledi. Haklı olabilirler - biraz okudum ama başımı veya yazıyı kendim yapamadım.


*Ve arasındaki boşluğun herhangi bir nedeni var mı .*?
Hashim

2
@Hashim Ana dizininizdeki çıktısını karşılaştırın echo * .*ve echo *.*çalıştırın; aradaki fark açık olmalıdır. Aksi takdirde LMK ve ben açıklayacağım.
wjandrea

İlginçtir, böylece echo *gizli olmayan dosya ve klasörleri echo *.*gösterir , gizli olmayan dosyaları echo .*gösterir, tüm dosyaları echo * .*gösterir ve tüm dosya ve klasörleri gösterir. Peki neden bu ikinci durumda ikisi arasındaki boşluğun nedeni? Bana dağınık geliyor. Aynı sonuçları elde etmek için ikisini birleştirmenin bir yolu yok mu? Ya da aksi halde, ikisinin neden burada ayrılması gerektiğine dair bir sözdizimi açıklaması var mı, yoksa * .*istisnai bir durum mu?
Hashim

1
@Hashim Bu sonuçlara nasıl ulaştığınızdan emin değilim, bu yüzden açıklamama izin verin. İlk olarak, dizinler bu bağlamdaki dosyalardır. Neználkovo olarak, *olmayan tüm gizli dosyaları temsil (yani dosya adları olan yok bir nokta ile başlar); .*(yani dosya adları tüm gizli dosyaları temsil do bir nokta ile başlar); ve bir nokta içeren*.* tüm gizli olmayan dosyaları temsil eder . İçinde iki küre ayrı olmalıdır, çünkü bunlar farklı kürelerdir: biri gizlenmemiş, biri gizlenmemiş. Cevabımı yazdığım gibi , kabuk seçeneğini açarak gizli dosyaları dahil edebilirsiniz . echo * .**dotglob
wjandrea

1
*.*Bütün dosyaları listelemek için Windows (DOS) 'u kullanmak yaygındır, ancak * nix, üzerinde sadece bir nokta bulunan dosyaları içerecektir, bu yüzden * nix üzerinde bir anlam ifade etmemektedir. Bunun yerine *, gizli dosyalar dışındaki tüm dosyaları .*listelemek ve gizli dosyaları listelemek için kullanın.
thomasrutter

10

-d skipEklenen seçeneğe ihtiyacınız var.

  1. Grep dosyaların içinde arama yapıyor. Bir dizinin içindeki dosyaları aramak istiyorsanız, dediğiniz gibi özyinelemeli arama yapabilirsiniz.

  2. Varsayılan olarak, grep tüm dosyaları okuyacak ve dizinleri tespit edecektir. Varsayılan olarak, -dseçeneklerin bulunduğu dizinlerle ne yapılacağını tanımlamadığınızdan , hata çıktısı verir.

  3. Sadece ana dizinde arama yapmak `grep -d atla" string "./*


Grep hakkında daha fazla bilgi için, bkz man grep.
Anonim2

(a) Lütfen düzenlemeye bakınız. (b) Kullanım -d skipişe yaramazsa; temelde aynıdır -s; ayrıca, düzenlemeye bakın. (c) Hayır, grep -d skip "string" ./*ya da çalışmıyor.
John Red

7

Eski zamanlayıcılar muhtemelen bunu yapar:

find . -type f -print0 | xargs -0 grep "string"

3
Neden olmasın find . -type f -exec grep string {} +?
wchargin

5
Sen de istiyorsun -maxdepth 1.
wchargin

@ wchargin: Çıktıda sadece bir dosya olduğunda çıktıda dosya ismini istiyorsanızfind . -type f -maxdepth 1 -exec grep string /dev/null {} +
Gregory Nisbet

1
@GregoryNisbet: Sadece grep'e geçin -H.
wchargin

2

Rephrasing - dosyaları bir alt dizinde bir seviyeye getirmek istiyorsunuz, ancak tüm alt alt dizinlere rağmen tekrarlamıyor musunuz?

grep forthis  *  */*

Veya dosyaları geçerli dizinde istemiyorsanız

grep forthis  */*

Bunun bir noktayla başlayan dizinleri bulamayacağını unutmayın.

grep forthis  .*/*    */*   

bu işi yapmalı.

Orada da var -maxdepthve -mindepthkısıtlama mevcut parametreler findde komuta.


Olmaz grep forthis */*geçerli dizinde ve bir dizin aşağı dosyaları hem search?
Hashim

@Hashim hayır çoğunlukla - çünkü */*sadece bir eğik çizgi ile eşleşir. Eğer a/bmevcut dizinde isminde bir dosya varsa , `* / * bununla eşleşir.
Criggie

0

İşte tüm hataları atlamaksızın dizinleri atlamak için bir örnek:

grep --directories='skip' 'searchString' *
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.