Bagaimana cara saya menerjang secara rekursif?

1682

Bagaimana saya secara rekursif grepsemua direktori dan subdirektori?

find . | xargs grep "texthere" *
wpiri
sumber
110
@ TC1 Yang menyedihkan adalah bahwa grep sendiri dapat menjawab pertanyaan (setidaknya GNU grep): grep --help | grep rekursif
Frank Schmitt
7
Jika Anda sering menggunakan grep untuk melakukan pencarian rekursif (terutama jika Anda secara manual melakukan banyak pengecualian file / direktori), Anda mungkin menemukan ack (alternatif grep yang sangat ramah-programmer) berguna.
Nick McCurdy
19
Sebenarnya bukan -r atau --recursive work pada kotak Solaris yang saya gunakan di tempat kerja. Dan halaman manual untuk grep tidak menyebutkan sesuatu yang rekursif. Saya harus mencari dan mencari sendiri.
Ben
8
ag adalah cara favorit saya untuk melakukan ini sekarang github.com/ggreer/the_silver_searcher
dranxo
1
grep -rin xlsx *.pltidak bekerja untuk saya di Redhat Linux. Saya mendapatkan kesalahan "tidak cocok".
Bulrush

Jawaban:

2507
grep -r "texthere" .

Parameter pertama mewakili ekspresi reguler untuk dicari, sedangkan yang kedua mewakili direktori yang harus dicari. Dalam hal ini, .berarti direktori saat ini.

Catatan: Ini berfungsi untuk grep GNU, dan pada beberapa platform seperti Solaris Anda harus secara khusus menggunakan grep GNU sebagai lawan implementasi legacy. Untuk Solaris ini adalah ggrepperintahnya.

Vinko Vrsalovic
sumber
39
Catatan: "grep -r" hanya bekerja pada greps yang lebih baru. Itu tidak berfungsi pada grep yang datang dengan AIX 5.3misalnya.
Dirahasiakan
110
Gunakan grep -R untuk mengikuti symlinks.
Eloff
53
Adalah baik untuk mengetahui bahwa "-i" akan membuatnya case-sensitive, dan "-n" juga termasuk nomor baris untuk setiap hasil yang cocok.
Sadegh
24
juga bagus untuk diketahui, jika Anda hanya mencari string tetap dan bukan regex, gunakan opsi -F. ini akan menghemat waktu Anda dengan tidak memanggil parser regex. sangat berguna jika Anda mencari banyak file.
Jeff
6
alias rgrep = 'grep -r'
totten
679

Jika Anda tahu ekstensi atau pola file yang Anda inginkan, metode lain adalah menggunakan --includeopsi:

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

Anda juga dapat menyebutkan file yang akan dikecualikan --exclude.

Ag

Jika Anda sering mencari melalui kode, Ag (The Silver Searcher) adalah alternatif yang jauh lebih cepat daripada grep, yang disesuaikan untuk mencari kode. Sebagai contoh, ini bersifat rekursif secara default dan secara otomatis mengabaikan file dan direktori yang terdaftar .gitignore, sehingga Anda tidak harus terus melewati opsi pengecualian yang rumit untuk diambil atau ditemukan.

pembaptisan
sumber
3
Bekerja sangat baik dengan grep yang hadir dengan Linux & Cygwin, tetapi tidak dengan grep yang datang dengan AIX.
Dirahasiakan
1
@ KrzysztofWolny: `` alih-alih =berfungsi dengan baik di Ubuntu. PS: itu seharusnya adalah ruang backticked, tetapi parser penurunan harga SO gagal.
Dan Dascalescu
4
@DanDascalescu Saya memilih untuk grep, bukan untuk Ag, asal kau tahu :)
Bernhard
1
Apakah kita memiliki opsi untuk mengecualikan direktori saat mencari secara rekursif?
Tom Taylor
Windows cygwin suka tanda kutip ganda--include "*.txt" --include "*.TXT"
Bob Stein
127

Juga:

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

tetapi grep -rmerupakan jawaban yang lebih baik.

Kurt
sumber
14
Atau jika Anda tidak ingin khawatir tentang spasi dalam nama file find . -type f -exec grep "foo" '{}' \;berfungsi dengan baik jika didukung.
Edd Steel
4
Jika Anda akan mencari pipa melalui xargs ke grep, DAN jika Anda hanya mencari string tetap (yaitu, bukan regex), Anda mungkin mendapat manfaat dari memohon opsi grep -F, jadi grep tidak akan memuat mesin regex untuk setiap doa. Jika ada banyak file akan jauh lebih cepat.
Jeff
2
Temukan . -type f -exec grep -Hu "foo" {} \; adalah apa yang saya gunakan karena memberikan nama file.
Wes
Ini berfungsi pada semua * nix karena POSIX 7
Ciro Santilli 郝海东 冠状 病 六四 事件 事件
1
find ./ -type f -print0 | xargs -0 grep "foo"
aehlke
118

Sekarang saya selalu menggunakan (bahkan di Windows dengan GoW - Gnu di Windows ):

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

Itu termasuk opsi berikut:

--include=PATTERN

Berulang dalam direktori hanya mencari pencocokan file PATTERN.

-n, --line-number

Awali setiap baris output dengan nomor baris di dalam file inputnya.

(Catatan: phuclv menambahkan komentar yang sangat -nmengurangi kinerja , jadi Anda mungkin ingin melewatkan opsi itu)

-R, -r, --recursive

Baca semua file di bawah setiap direktori, secara rekursif; ini setara dengan -d recurseopsi.

-H, --with-filename

Cetak nama file untuk setiap kecocokan.

-I     

Memproses file biner seolah-olah tidak mengandung data yang cocok;
ini setara dengan --binary-files=without-matchopsi.

Dan saya dapat menambahkan ' i' ( -nRHIi), jika saya ingin hasil case-insensitive.

Saya bisa mendapatkan:

/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;
...
VONC
sumber
Gow terlihat menjanjikan - lebih baru dari pada utilitas Windows GNU yang telah saya gunakan.
Cobalah
apa arti dari karakter terakhir * di sini?
lorniper
2
@Lorniper membuat shell memilih semua file dan folder di direktori Anda saat ini, membuat grep berlaku untuk file-file tersebut dan (secara rekursif karena -Ropsi) ke folder.
VonC
2
@lorniper Noy persis: *atau .merupakan pola glob (ditafsirkan oleh shell): unix.stackexchange.com/a/64695/7490 . ' .' akan memilih dotfile atau folder dot juga (seperti .git/)
VonC
sebelumnya saya selalu menggunakan grep -rnItetapi kemudian saya belajar bahwa banyak -nmenurunkan kinerja jadi saya hanya menggunakannya ketika benar-benar diperlukan dan biasanya saya akan menggunakan-rI
phuclv
25

Dalam sistem POSIX, Anda tidak menemukan -rparameter untuk grepdan Anda grep -rn "stuff" .tidak akan berjalan, tetapi jika Anda menggunakan findperintah itu akan:

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

Disetujui oleh Solarisdan HP-UX.

benteng
sumber
apa arti dari {} \; -cetak masing-masing?
user1169587
3
Dalam -execopsi - simbol {}adalah referensi ke nama file yang saat ini ditemukan oleh findalat (yaitu melakukan sesuatu dengan nama file yang kami temukan), juga -execopsi harus diakhiri dengan ;simbol (untuk menandai akhir dari perintah exec), tetapi karena ini semua berjalan di shell bahwa simbol harus melarikan diri .. dan akhirnya -printopsi memungkinkan findalat untuk mencetak nama file yang ditemukan di layar.
benteng
19

globbing **

Menggunakan grep -rkarya, tetapi mungkin berlebihan, terutama di folder besar.

Untuk penggunaan yang lebih praktis, ini adalah sintaks yang menggunakan sintaks globbing ( **):

grep "texthere" **/*.txt

yang hanya menangkap file tertentu dengan pola pola yang dipilih. Ia bekerja untuk cangkang yang didukung seperti Bash +4 atau zsh .

Untuk mengaktifkan fitur ini, jalankan: shopt -s globstar.

Lihat juga: Bagaimana cara menemukan semua file yang mengandung teks tertentu di Linux?

git grep

Untuk proyek-proyek di bawah kendali versi Git, gunakan:

git grep "pattern"

yang jauh lebih cepat.

ripgrep

Untuk proyek yang lebih besar, alat grepping tercepat adalah ripgrepgreps file secara rekursif secara default:

rg "pattern" .

Itu dibangun di atas mesin regex Rust yang menggunakan automata terbatas, SIMD dan optimasi literal agresif untuk membuat pencarian sangat cepat. Periksa analisis terperinci di sini .

kenorb
sumber
3
Terima kasih atas saran git grep - ini sangat berguna dan saya tidak tahu tentang itu!
Basya
2
Terima kasih atas saran ripgrep. Itu jauh lebih cepat.
What Would Be Cool
11

Untuk menemukan nama filesdengan pathsecara rekursif yang stringmenggunakan perintah khusus di bawah ini untuk UNIX:

find . | xargs grep "searched-string"

untuk Linux:

grep -r "searched-string" .

cari file di UNIXserver

find . -type f -name file_name

cari file di server LINUX

find . -name file_name
Girdhar Singh Rathore
sumber
11

hanya nama file yang bisa bermanfaat juga

grep -r -l "foo" .
chim
sumber
10

Jika Anda hanya ingin mengikuti direktori aktual, dan bukan tautan simbolik,

grep -r "thingToBeFound" directory

Jika Anda ingin mengikuti tautan simbolik serta direktori aktual (berhati-hatilah terhadap rekursi tak terbatas),

grep -R "thing to be found" directory

Karena Anda mencoba untuk menerjang secara rekursif, opsi berikut ini mungkin juga berguna bagi Anda:

-H: outputs the filename with the line

-n: outputs the line number in the file

Jadi jika Anda ingin menemukan semua file yang mengandung Darth Vader di direktori saat ini atau subdirektori apa pun dan menangkap nama file dan nomor baris, tetapi tidak ingin rekursi mengikuti tautan simbolik, perintahnya adalah

grep -rnH "Darth Vader" .

Jika Anda ingin menemukan semua sebutan kata cat di direktori

/home/adam/Desktop/TomAndJerry 

dan Anda saat ini berada di direktori

/home/adam/Desktop/WorldDominationPlot

dan Anda ingin mengambil nama file tetapi bukan nomor baris dari sembarang string "kucing", dan Anda ingin rekursi mengikuti tautan simbolis jika menemukannya, Anda bisa menjalankan salah satu dari berikut ini

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

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

Sumber:

menjalankan "grep --help"

Pengantar singkat untuk tautan simbolik, bagi siapa pun yang membaca jawaban ini dan bingung dengan referensi saya kepada mereka: https://www.nixtutor.com/freebsd/understanding-symbolic-links/

SarcasticSully
sumber
Jawaban yang bagus Switch tambahan (-rnh) sangat membantu, jadi terima kasih telah menyarankannya.
semtex41
8

ag adalah cara favorit saya untuk melakukan ini sekarang github.com/ggreer/the_silver_searcher . Ini pada dasarnya hal yang sama dengan ACK tetapi dengan beberapa optimasi lagi.

Inilah patokan singkat. Saya menghapus cache sebelum setiap tes (lih. Https://askubuntu.com/questions/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
dranxo
sumber
6

Ini seharusnya bekerja:

grep -R "texthere" *
sumit kumar
sumber
6

Jika Anda mencari konten tertentu di semua file dari struktur direktori, Anda dapat menggunakannya findkarena lebih jelas apa yang Anda lakukan:

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

Perhatikan bahwa -l(huruf kecil L) menunjukkan nama file yang berisi teks. Hapus itu jika Anda ingin mencetak pertandingan itu sendiri. Atau gunakan -Huntuk mendapatkan file bersama dengan pertandingan. Secara keseluruhan, alternatif lain adalah:

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

Di mana -nmencetak nomor baris.

fedorqui 'SO berhenti merugikan'
sumber
2
Terpilih sebagai satu-satunya findsolusi untuk menghindari penggunaan yang tidak perlu xargsdan penggunaan +alih-alih \;dengan -exec, dengan demikian menghindari berton-ton proses peluncuran yang tidak perlu. :-)
ShadowRanger
6

Ini adalah yang bekerja untuk kasus saya di mesin saya saat ini (git bash di windows 7):

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

Saya selalu lupa -print0 dan -0 untuk path dengan spasi.

Sunting: Alat pilihan saya sekarang bukan ripgrep: https://github.com/BurntSushi/ripgrep/releases . Ini sangat cepat dan memiliki standar yang lebih baik (seperti rekursif secara default). Contoh yang sama dengan jawaban asli saya tetapi menggunakan ripgrep:rg -g "*.cs" "content pattern"

bahtera
sumber
4

grep -r "texthere" . (periode pemberitahuan di akhir)

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


Klarifikasi:

grep -r "texthere" /(grep semua direktori dan subdirektori secara rekursif )

grep -r "texthere" .(rekursif grep ini direktori dan subdirektori)

grep rekursif

grep [options] PATTERN [FILE...]

[pilihan]

-R, -r, --recursive

Baca semua file di bawah setiap direktori, secara rekursif.

Ini sama dengan opsi -d recurseatau --directories=recurse.

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

bantu grep

$ grep --help

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

Alternatif

ack( http://beyondgrep.com/ )

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

Geoffrey Hale
sumber
4

Pada 2018, Anda ingin menggunakan ripgrepatau the-silver-searcherkarena mereka jauh lebih cepat daripada alternatifnya.

Berikut adalah direktori dengan 336 subdirektori tingkat pertama:

% 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

Pada OSX, ini akan menginstal ripgrep: brew install ripgrep. Ini akan menginstal silver-searcher: brew install the_silver_searcher.

hughdbrown
sumber
Kecepatan penting jika Anda perlu melakukan ini sering, tetapi kebanyakan dari kita mendapati diri kita hanya melakukan ini paling banyak beberapa kali setahun. Menginstal alat juju pihak ketiga yang rumit dan baru-baru ini terlalu berat dan solusi yang tidak banyak berubah sejak 1978 baik untuk diketahui.
rangkap tiga
Saya merasa sangat tidak masuk akal bahwa seorang programmer akan mencari teks di pohon sumber hanya beberapa kali per tahun. Tetapi bahkan dari sudut pandang kegunaan, rgmemiliki keunggulan yang cukup besar dalam membuat perintah grep rekursif dari awal. Menggunakan rg: rg foo. Menggunakan alat unix: find . | xargs grep foo. Dan jika ada file Anda yang memiliki kutipan di dalamnya, Anda perlu menggunakannya find . -print0 | xargs -0 grep foo. Apakah Anda akan ingat bahwa jika Anda menggunakannya beberapa kali dalam setahun?
hughdbrown
1
Anda lupa find . -type f -exec grep 'regex' {} +yang memang mudah diingat jika Anda menggunakan alat ini dengan teratur. Tetapi mungkin Anda harus menjalankan ctagsatau etagspada pohon sumber Anda jika Anda perlu menemukan barang-barang sering.
tripleee
Saya telah menggunakan ripgrep dan itu bagus. Tapi pencari perak sangat bagus untuk programmer. +1
Matt
3

Di IBM AIX Server saya (versi OS: AIX 5.2), gunakan:

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

ini akan mencetak path / nama file dan nomor baris relatif dalam file seperti:

./inc/xxxx_x.h

2865: / ** Keterangan: stringYouWannaFind * /

bagaimanapun, ini bekerja untuk saya :)

pengguna3606336
sumber
3

Di bawah ini adalah perintah untuk pencarian Stringdi lingkungan Unixdan rekursif Linux.

untuk UNIXperintah adalah:

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

untuk Linuxperintah adalah:

grep -r "string to be searched" .
Girdhar Singh Rathore
sumber
2

Untuk daftar bendera yang tersedia:

grep --help 

Mengembalikan semua kecocokan untuk teks regexp di direktori saat ini, dengan nomor baris yang sesuai:

grep -rn "texthere" .

Mengembalikan semua kecocokan untuk texthere , mulai dari direktori root, dengan nomor baris yang sesuai dan mengabaikan case:

grep -rni "texthere" /

bendera yang digunakan di sini:

  • -r rekursif
  • -n cetak nomor baris dengan output
  • -i abaikan case
JSON C11
sumber
1

Saya kira inilah yang ingin Anda tulis

grep myText $(find .)

dan ini mungkin sesuatu yang bermanfaat jika Anda ingin menemukan file grep hit

grep myText $(find .) | cut -d : -f 1 | sort | uniq
Victor Faria
sumber
Ini sangat intuitif: misalnya: grep -i acc $ (temukan. -Nama "eksekusi *. *")
Yu Shen
1

Melemparkan dua sen saya di sini. Seperti yang telah disebutkan orang lain grep -r tidak bekerja di setiap platform. Ini mungkin terdengar konyol tapi saya selalu menggunakan git.

git grep "texthere"

Bahkan jika direktori tersebut tidak dipentaskan, saya hanya menjalankannya dan menggunakan git grep.

Zstack
sumber
0

Perhatikan bahwa find . -type f | xargs grep whateverberbagai jenis solusi akan mengalami kesalahan "Daftar argumen sampai panjang" ketika ada terlalu banyak file yang cocok dengan find.

Taruhan terbaik adalah grep -rtetapi jika itu tidak tersedia, gunakan find . -type f -exec grep -H whatever {} \;saja.

m
sumber
Hah? xargssecara khusus merupakan solusi untuk masalah "Daftar argumen terlalu panjang".
tripleee
2
Ya, tidak - xargs khusus untuk mengonversi pipa argumen menjadi arglist, tapi ya, memang benar bahwa xargs modern ketika digunakan dengan -s dan / atau -L dapat menangani argumen yang sangat panjang dengan memecah menjadi beberapa perintah perintah, tetapi itu tidak dikonfigurasi dengan cara itu secara default (dan tidak ada di salah satu dari respons di atas). Sebagai contoh:find . -type f | xargs -L 100 grep whatever
m.thome
Di platform mana itu? POSIXxargs distandarisasi untuk memiliki perilaku ini di luar kotak. " xargsUtilitas akan membatasi panjang baris perintah sehingga ketika baris perintah dipanggil, argumen gabungan dan daftar lingkungan ... tidak boleh melebihi {ARG_MAX} -2048 byte."
tripleee
Hm Meskipun dokumen gnu kurang jelas daripada posix atas dasar ini, dan saya tidak lagi memiliki akses ke mesin yang menyebabkan saya membuat pernyataan ini, saya tidak dapat mengkonfirmasi interpretasi asli saya tentang implementasi saat ini. Grep rekursif, tentu saja, masih lebih disukai jika tersedia, tetapi ada sedikit alasan untuk menghindari resep xargs (jangan gunakan -H untuk grep untuk menghindari permintaan akhir dari grep yang hanya melewati satu nama file saja).
m.thome
0

Hanya untuk bersenang-senang, pencarian cepat dan kotor file * .txt jika jawaban @christangrant terlalu banyak untuk diketik :-)

grep -r texthere .|grep .txt

PJ Brunet
sumber
0

Berikut ini adalah fungsi rekursif (diuji ringan dengan bash dan sh) yang melintasi semua subfolder dari folder tertentu ($ 1) dan menggunakan greppencarian untuk string yang diberikan ($ 3) dalam file yang diberikan ($ 2):

$ 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"

Menjalankannya dan contoh output:

$ sh script start_folder filename search_string
/home/james/start_folder/dir2/filename
James Brown
sumber
-2
The syntax is:
cd /path/to/dir
grep -r <"serch_word name"> .
Sial
sumber
7
Ini tidak menambah banyak jawaban lain
Mel