find และ echo ชื่อไฟล์ที่พบรูปแบบเท่านั้น


16

ฉันใช้มันมากการปรับปรุงที่ฉันพยายามทำให้สำเร็จคือการหลีกเลี่ยงชื่อไฟล์ echo ที่ไม่ตรงกับ grep วิธีที่ดีกว่าในการทำเช่นนี้?

    for file in `find . -name "*.py"`; do echo $file; grep something $file; done

คำตอบ:


24
find . -name '*.py' -exec grep something {} \; -print

จะพิมพ์ชื่อไฟล์หลังจากบรรทัดที่ตรงกัน

find . -name '*.py' -exec grep something /dev/null {} +

จะพิมพ์ชื่อไฟล์ในด้านหน้าของการจับคู่สายทุก (เราเพิ่ม/dev/nullสำหรับกรณีที่มีเพียงหนึ่งไฟล์ที่ตรงกันเป็นgrepไม่ได้พิมพ์ชื่อไฟล์ถ้ามันผ่านไปเพียงหนึ่งไฟล์ที่จะมองใน. ลิขสิทธิ์ GNU การดำเนินการgrepมี-Hตัวเลือกสำหรับการที่ เป็นทางเลือก)

find . -name '*.py' -exec grep -l something {} +

จะพิมพ์เฉพาะชื่อไฟล์ของไฟล์ที่มีอย่างน้อยหนึ่งบรรทัดที่ตรงกัน

หากต้องการพิมพ์ชื่อไฟล์ก่อนบรรทัดที่ตรงกันคุณสามารถใช้ awk แทน:

find . -name '*.py' -exec awk '
  FNR == 1 {filename_printed = 0}
  /something/ {
    if (!filename_printed) {
      print FILENAME
      filename_printed = 1
    }
    print
  }' {} +

หรือเรียกgrepสองครั้งสำหรับแต่ละไฟล์ - แม้ว่ามันจะมีประสิทธิภาพน้อยลงเพราะมันจะทำงานอย่างน้อยหนึ่งgrepคำสั่งและมากถึงสองสำหรับแต่ละไฟล์ (และอ่านเนื้อหาของไฟล์สองครั้ง):

find . -name '*.py' -exec grep -l something {} \; \
                    -exec grep something {} \;

ในกรณีใด ๆที่คุณไม่ต้องการที่จะห่วงมากกว่าการส่งออกของfindเช่นนั้นและอย่าลืมที่จะพูดตัวแปรของคุณ

หากคุณต้องการใช้เชลล์วนกับเครื่องมือ GNU:

find . -name '*.py' -exec grep -l --null something {} + |
   xargs -r0 sh -c '
     for file do
       printf "%s\n" "$file"
       grep something < "$file"
     done' sh

(ใช้ได้กับ FreeBSD และอนุพันธ์)


6

หากคุณใช้ GNU grep คุณสามารถใช้-rหรือ--recursiveตัวเลือกเพื่อค้นหาสิ่งที่ง่ายสำหรับคุณ:

grep -r --include '*.py' -le "$regexp" ./ # for filenames only
grep -r --include '*.py' -He "$regexp" ./ # for filenames on each match

คุณต้องการเพียงfindถ้าคุณต้องการเพรดิเคตขั้นสูง


1
ทั้งนี้ขึ้นอยู่กับรุ่นของ GNU grep, grepหรืออาจจะไม่ดูภายใน symlinks หรือ symlinks การสำรวจไปยังไดเรกทอรี นอกจากนี้คุณยังอาจพบความแตกต่างบางอย่างในการจัดการไฟล์ประเภทอื่นที่ไม่ใช่ไฟล์ปกติ
Stéphane Chazelas

5

คุณสามารถบอก grep ให้รวมชื่อไฟล์ในผลลัพธ์ ดังนั้นหากมีการแข่งขันจะปรากฏบนคอนโซล หากไม่มีการจับคู่ภายในไฟล์จะไม่มีการพิมพ์บรรทัดสำหรับไฟล์นั้น

find . -name "*.py" | xargs grep -n -H something

จากman grep:

-H       Always print filename headers with output lines
-n, --line-number
         Each output line is preceded by its relative line number in the file, starting at line 1.  The line number counter is reset for each file processed.
         This option is ignored if -c, -L, -l, or -q is specified.

หากไฟล์ของคุณอาจมีชื่อที่มีช่องว่างคุณต้องสลับไปป์เพื่อใช้อักขระ NUL เป็นตัวคั่น คำสั่งเต็มจะมีลักษณะเช่นนี้:

find . -name "*.py" -print0 | xargs -0 grep -n -H something

1

คุณสามารถลองสิ่งต่อไปนี้:

find . -name "*.py:" -exec grep -l {} \;

คำสั่ง exec grep นี้สำหรับทุกไฟล์ค้นพบโดยคำสั่ง find และคุณลักษณะคำสั่งค้นหามาตรฐาน


1

ใช้-lอาร์กิวเมนต์

for file in `find . -name "*.py"`; do grep -l something $file && grep something $file; done

การใช้งาน findish เพิ่มเติมจะเป็น:

for file in $(find . -name '*.py' -exec grep -l something '{}' +); do echo "$file"; grep something $file; done

1

มีgrepทางเลือกที่โดยค่าเริ่มต้นผลลัพธ์ของพวกเขาในรูปแบบที่คุณต้องการ 2 คนนิยมมากที่สุดที่ฉันรู้ว่ามีอยู่ag(aka "ค้นหาเงิน") ackและ เป็นโฆษณาที่ให้ทางเลือกที่เร็วขึ้นagack

$ ag '^\w+\s*\w+\(' ~/build/i3/src
build/i3/src/display_version.c
58:void display_running_version(void) {

build/i3/src/load_layout.c
42:static TAILQ_HEAD(focus_mappings_head, focus_mapping) focus_mappings =
518:json_content_t json_determine_content(const char *filename) {
575:void tree_append_json(Con *con, const char *filename, char **errormsg) {

build/i3/src/x.c
64:CIRCLEQ_HEAD(state_head, con_state) state_head =
67:CIRCLEQ_HEAD(old_state_head, con_state) old_state_head =
70:TAILQ_HEAD(initial_mapping_head, con_state) initial_mapping_head =
97:void x_con_init(Con *con, uint16_t depth) {
...

ฉันไม่สามารถแสดงให้คุณเห็นที่นี่ได้ ฉันได้ชื่อไฟล์เป็นสีเขียวมะกอกหมายเลขบรรทัดเป็นสีเหลืองทองและชิ้นส่วนที่ตรงกันในแต่ละบรรทัดด้วยสีแดงเลือด สีที่สามารถปรับแต่งได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.