Bash: adakah cara untuk mencari string tertentu dalam direktori file? [duplikat]

47

Kemungkinan Duplikat:
Cari pola teks di linux

Dalam bash, saya bertanya-tanya apakah ada perintah yang akan memberi tahu Anda jika string tertentu yang Anda cari ada di dalam file yang terletak di direktori saat ini Anda berada.

Katakanlah Anda mencari fungsi 'toUpperCase ()' dalam satu set file C di direktori Anda saat ini. Ada banyak file, jadi Anda tidak ingin membukanya secara manual menggunakan vim dan memeriksa string 'toUpperCase' karena itu akan memakan banyak waktu. Jika bukan bash command line, apakah ada metode lain untuk melakukan ini secara efisien?

Dark Templar
sumber

Jawaban:

64

Dengan grep:

grep -R "toUppercase()" *

Atau, jika Anda telah menginstal ack-grep , cukup:

ack-grep "toUppercase"

Jika Anda ingin membatasi pencarian dalam file C, dengan ack-grep:

ack-grep -cc "toUppercase()"

ack-grepjuga dapat diinstal pada OSX tetapi yang dapat dieksekusi disebut adil ack.

Trasplazio Garzuglio
sumber
Sedemikian rupa sehingga SO sudah memiliki pertanyaan serupa yang mencurigakan ;)
David Perry
10

Alat pencarian teks standar adalah grep .

Untuk mencari string toUpperCase(di semua .cfile di direktori saat ini:

grep -F 'toUpperCase(' *.c

Jika Anda ingin mencari di subdirektori juga:

grep -r --include='*.c' -F 'toUpperCase('

Jika Anda mencari panggilan fungsi C, maka ctag mungkin lebih cocok. Anda menjalankannya sekali pada semua file sumber Anda untuk membuat indeks pengidentifikasi, lalu gunakan editor Anda untuk bernavigasi di antara panggilan. Semua editor mirip vi dapat menggunakan TAGSfile ctags . Jika Anda menggunakan Emacs, jalankan program serupa etags.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
ctagsberguna untuk menemukan definisi fungsi , bukan panggilan fungsi .
JdeBP
6

Anda menggunakan vim. Anda punya alat untuk melakukan ini.

Bisa ditebak, ada tujuh jawaban yang sudah mengatakan untuk digunakan grep. Tetapi saya tampaknya menjadi satu-satunya orang yang sejauh ini telah memperhatikan dari pertanyaan Anda yang Anda gunakan vim. Dengan demikian, meskipun Anda dapat menggunakan grepdari dalam vim, Anda juga dapat menggunakan vimalat bawaan. Ini dipanggil melalui :vimgrepperintah.

Untuk mencari "semua file sumber C di direktori saat ini untuk panggilan ke fungsi toUpperCase()" satu ketik vimperintah

:vimgrep "\<toUpperCase\_s*(" *.c

Daftar kecocokan yang dihasilkan secara otomatis dimuat ke dalam daftar perbaikan cepat, dapat diakses dengan salah satu dari (lihat bantuan on-line untuk perbedaan halus)

:copen
:cwin

Untuk menemukan definisi fungsi , bukan panggilan ke sana, ctagsadalah alat, seperti yang disebutkan dalam Gillesjawaban , dalam hubungannya dengan perintah :tjumpatau :tselect.

Mengapa menggunakan :vimgrep?

Bantuan online ( :help grep) menyebutkan beberapa alasan, yang saya tidak akan nuri di sini. Lebih jauh dari itu, bandingkan tindakan :vimgrepdengan dietbuddhajawaban . dietbuddhaBaris perintah memotong grepproses individu untuk setiap file sumber C individu. Bahkan tidak digunakan xargsuntuk mengurangi overhead itu. Dan Anda masih harus mem-parsing output untuk memanggil editor teks Anda pada file sumber yang relevan setelah selesai. :vimgreptidak memotong beberapa proses tambahan sama sekali, dan menggunakan hasilnya adalah kesederhanaan itu sendiri. Hanya memilih salah satu entri dalam daftar perbaikan cepat yang dihasilkan secara otomatis menempatkan kursor pada baris yang relevan dari file sumber yang relevan.

Bahkan, ia melakukan persis apa yang Anda tuliskan dengan tangan, kecuali secara otomatis. Ini adalah cara otomatis untuk melakukan tindakan editor teks tersebut. Ini memuat file seolah-olah dimuat dengan tangan, mencarinya untuk ekspresi reguler (menggunakan sintaks ekspresi reguler yang sama yang sudah Anda gunakan di tempat lain vim), mencatat tempat-tempat yang cocok, dan kemudian membongkar file.

JdeBP
sumber
2

Ya, alat ini disebut grep.

Perintah grep mencari satu atau lebih file input untuk baris yang berisi kecocokan dengan pola yang ditentukan. Secara default, grep mencetak garis yang cocok.

Penggunaan dasar adalah:

grep something somewhere

Atau, lebih khusus:

grep [some options] pattern file

Dalam kasus yang sangat sederhana, Anda ingin mencari semua file secara rekursif, sehingga Anda memberikan -ropsi. Jika Anda tidak peduli dengan huruf besar atau kecil, buatlah huruf besar-kecil dengan -iopsi.

grep -ri "touppercase()" .

Jika Anda hanya menginginkan bagian yang cocok, gunakan -oopsi.

Grep dapat menggunakan ekspresi reguler , dan memiliki manual besar .

slhck
sumber
2

grepadalah jawaban standar - menggunakan bendera -r untuk mencari secara rekursif atau bersamaan find(diskusi dan contoh dalam pertanyaan lain di situs ini, seperti yang ini )

Pilihan pilihan saya belakangan ini adalah ack. Ini sepertinya tidak diinstal pada komputer Anda, tetapi Anda dapat menginstal menggunakan apt-get di Ubuntu atau hanya mengunduh. Tautan, instruksi, dan alasan yang lebih baik daripada grep tersedia di http://betterthangrep.com/

Doug Harris
sumber
1

find dan grep

find myproject -name '*.c' -exec grep 'toUpperCase(' {} \; -print

kenapa tidak saja grep?

grep -r string .akan berulang melalui semua file di direktori saat ini. Jika Anda memiliki file objek atau binari lain, Anda mungkin mendapatkan kecocokan dengan hasil biner alias. sampah Jika Anda juga memiliki file fifos atau perangkat di subdirektori, Anda mungkin memiliki konsekuensi yang tidak diketahui / tidak diinginkan.

grep string *.chanya mencari .cfile direktori saat ini .

grep string **/*.c tidak mencari semua subdirektori. Namun, jika Anda memiliki jumlah .cfile yang sangat besar, Anda berisiko melebihi jumlah maksimum ekspansi untuk shell glob. Perluasan juga harus terjadi terlebih dahulu yang berarti melintasi pohon penuh sebelum grepdimulai.

dietbuddha
sumber
0

Grep akan melakukan triknya, tetapi sedikit skrip tambahan akan membantu menemukan nama file dan baris yang dirujuk. Jika itu yang Anda inginkan, saya menemukan yang berikut ini berfungsi dengan baik. Saya menyimpannya sebagai skrip shell dan memberikannya nilai yang saya inginkan sebagai opsi baris perintah pertama.

for i in $(ls)
do
    cat $i 2> /dev/null | grep $1 > /dev/null 2>&1
    STATUS=$?
    if [ $STATUS  -eq 0 ] ; then
        echo $i
        cat $i | grep -n $1
    fi
done
Tim Brigham
sumber
3
grep memiliki opsi -H yang sudah melakukannya. grep -Hn terserah *
Roy Rico
Pelajari sesuatu yang baru setiap hari .. Terima kasih @ Roy Rico
Tim Brigham
0

Saya merasa menarik bahwa tidak ada yang menjawab pertanyaan spesifik Anda: "bagaimana saya menemukan apakah string tertentu ada di dalam file yang terletak di direktori saat ini". Sejauh yang saya tahu tidak ada opsi grep yang hanya mengembalikan apakah kecocokan telah ditemukan dalam sekelompok file. Opsi terdekat adalah -l untuk mencantumkan nama file. Jawaban terdekat di antara mereka sejauh ini adalah dari tim, dengan sedikit perubahan:

#!/usr/bin/bash

for i in $(ls *.c 2> /dev/null)
do
    cat $i 2> /dev/null | grep $1 > /dev/null 2>&1
    STATUS=$?

    if [ $STATUS  -eq 0 ] ; then
        echo "Found"
        exit
    fi
done

echo "Not found"

Anda bisa menjadikan skrip shell ini lebih umum dengan menerima argumen kedua untuk ekstensi file tanpa terlalu banyak kesulitan.

doug

SnoopDougieDoug
sumber