ฉันจะค้นหาไฟล์ที่ไม่มีรูปแบบสตริงที่กำหนดได้อย่างไร


คำตอบ:


818

หาก grep ของคุณมีตัวเลือก-L(หรือ--files-without-match):

$ grep -L "foo" *

1
ตามที่ระบุไว้ที่อื่น ๆ ack ช่วยหลีกเลี่ยงไฟล์. svn (การโค่นล้ม) ตามค่าเริ่มต้น
GuruM

11
@GuruM สิ่งนี้สามารถทำได้ใน GNU grep โดยการส่งออกตัวแปรGREP_OPTIONS='--exclude-dir=.svn --exclude-dir=.git': ^)
bufh

6
หรือเทียบเท่าโดยใช้ag :ag -L 'foo'
อธิการ

5
ทำงานเหมือนเวทมนตร์! คำแนะนำ: ใช้-rLแทน-Lเพื่อจับคู่ไดเรกทอรีย่อย
Ufos

1
@ Larry - วิธีทำความสะอาดเพื่อหลีกเลี่ยงปัญหา globbing คือการใช้ตัวเลือกยาว "ว่าง" เช่นนี้: grep -L 'foo' -- *มาตรฐานคือคำสั่งที่ใช้ตัวเลือกยาวใช้--เพื่อระบุว่าไม่มีตัวเลือกเพิ่มเติมหลังจากจุดนี้
Paddy Landau

45

ackลองดูที่ มันจะ.svnยกเว้นสำหรับคุณโดยอัตโนมัติให้การแสดงออกปกติ Perl และให้คุณดาวน์โหลดง่าย ๆ ของโปรแกรม Perl เดียว

สิ่งที่คุณกำลังมองหาควรเทียบเท่าในack:

ack -L foo

23

คุณสามารถทำได้ด้วย grep เพียงอย่างเดียว (โดยไม่ต้องค้นหา)

grep -riL "foo" .

นี่คือคำอธิบายของพารามิเตอร์ที่ใช้ grep

     -L, --files-without-match
             each file processed.
     -R, -r, --recursive
             Recursively search subdirectories listed.

     -i, --ignore-case
             Perform case insensitive matching.

หากคุณใช้l(ลดระดับ) คุณจะได้สิ่งที่ตรงกันข้าม (ไฟล์ที่มีข้อมูลตรงกัน)

     -l, --files-with-matches
             Only the names of files containing selected lines are written

17

คำสั่งต่อไปนี้ให้ไฟล์ทั้งหมดที่ไม่มีรูปแบบfoo:

find .  -not  -ipath '.*svn*' -exec  grep  -H -E -o -c  "foo"  {} \; | grep 0

4
คุณต้องการเปลี่ยน grep 0 ที่ส่วนท้ายเป็น grep 0 $ (ไม่เช่นนั้นคุณจะได้รับการจับคู่ที่ผิดพลาดในไฟล์ที่มีอักขระ 0 ในชื่อไฟล์)
clouseau

9
@clouseau ส่วนใหญ่ถูกต้อง ... อย่างไรก็ตามgrep '0$'จะจับคู่ไฟล์ที่มีทวีคูณของ 10 บรรทัดด้วย! คุณต้องการgrep ':0$'ที่จะตรวจสอบ ': 0' ที่ท้ายบรรทัดอย่างชัดเจน จากนั้นคุณจะได้รับไฟล์ที่มีเส้นตรงเป็นศูนย์เท่านั้น
TrinitronX

UNIX ที่ฉันใช้อยู่ไม่มีเวอร์ชันค้นหาหรือ grep พร้อมตัวเลือกเหล่านี้ดังนั้นฉันต้องไปด้วยคำสั่ง "ack" ที่แนะนำในความคิดเห็นอื่น
KC Baltz

14

ไม่รวมคำสั่งต่อความจำเป็นในการค้นหาเพื่อกรองออกมาโฟลเดอร์โดยใช้เป็นครั้งที่สองsvngrep

grep -rL "foo" ./* | grep -v "\.svn"


6

ฉันโชคดีกับ

grep -H -E -o -c "foo" */*/*.ext | grep ext:0

ความพยายามของฉันgrep -vเพียงแค่ให้ทุกบรรทัดโดยไม่มี "foo"


4

ปัญหา

ฉันต้องการ refactor โครงการขนาดใหญ่ที่ใช้.phtmlไฟล์เพื่อเขียน HTML โดยใช้โค้ด PHP แบบอินไลน์ ฉันต้องการใช้เทมเพลตหนวดแทน ฉันต้องการหา.phtmlไจล์ซึ่งไม่มีสตริงnew Mustacheเนื่องจากยังคงต้องเขียนใหม่

สารละลาย

find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'

คำอธิบาย

ก่อนท่อ:

หา

find . ค้นหาไฟล์ซ้ำโดยเริ่มต้นในไดเรกทอรีนี้

-iname '*.phtml'ชื่อไฟล์ต้องมี.phtml( iทำให้ตัวพิมพ์เล็กและตัวพิมพ์ใหญ่)

-exec 'grep -H -E -o -c 'new Mustache' {}'รันgrepคำสั่งบนแต่ละพา ธ ที่ตรงกัน

grep

-H พิมพ์ส่วนหัวชื่อไฟล์ด้วยบรรทัดเอาต์พุตเสมอ

-E ตีความรูปแบบการแสดงออกปกติเพิ่มเติม (เช่นบังคับ grep เพื่อทำหน้าที่เป็น egrep)

-o พิมพ์เฉพาะส่วนที่ตรงกันของบรรทัด

-c เฉพาะจำนวนบรรทัดที่เลือกเท่านั้นที่ถูกเขียนไปยังเอาต์พุตมาตรฐาน


นี่จะให้รายการเส้นทางของไฟล์ทั้งหมดที่ลงท้าย.phtmlด้วยจำนวนครั้งที่สตริงnew Mustacheเกิดขึ้นในแต่ละไฟล์

$> find . -iname '*.phtml$' -exec 'grep -H -E -o -c 'new Mustache' {}'\;

./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
./app/MyApp/Customer/View/Account/studio.phtml:0
./app/MyApp/Customer/View/Account/orders.phtml:1
./app/MyApp/Customer/View/Account/banking.phtml:1
./app/MyApp/Customer/View/Account/applycomplete.phtml:1
./app/MyApp/Customer/View/Account/catalogue.phtml:1
./app/MyApp/Customer/View/Account/classadd.phtml:0
./app/MyApp/Customer/View/Account/orders-trade.phtml:0

ไพพ์แรกgrep :0$กรองรายการนี้เพื่อรวมเฉพาะบรรทัดที่ลงท้ายด้วย:0:

$> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$

./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
./app/MyApp/Customer/View/Account/studio.phtml:0
./app/MyApp/Customer/View/Account/classadd.phtml:0
./app/MyApp/Customer/View/Account/orders-trade.phtml:0

ไพsed 's/..$//'พ์ที่สองตัดอักขระสองตัวสุดท้ายของแต่ละบรรทัดทิ้งไว้เพียงพา ธ ของไฟล์

$> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'

./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml
./app/MyApp/Customer/View/Account/studio.phtml
./app/MyApp/Customer/View/Account/classadd.phtml
./app/MyApp/Customer/View/Account/orders-trade.phtml

3

หากคุณใช้คอมไพล์ระบบจะทำการค้นหาไฟล์ที่ถูกติดตามทั้งหมด:

git grep -L "foo"

และคุณสามารถค้นหาไฟล์ย่อยที่ถูกติดตามหากคุณเปิดไดเรกทอรีย่อย ** เปิดใช้งาน ( shopt -s globstarใน. bashrc ดูที่นี่ ):

git grep -L "foo" -- **/*.cpp

1

grep ของฉันไม่มีตัวเลือก -L ฉันหาวิธีแก้ปัญหาเพื่อให้ได้สิ่งนี้

ความคิดคือ:

  1. เพื่อดัมพ์ชื่อไฟล์ทั้งหมดที่มีสตริงที่เหมาะสมไปยัง txt1.txt
  2. ดัมพ์ชื่อไฟล์ทั้งหมดในไดเร็กทอรีไปยัง txt2.txt
  3. สร้างความแตกต่างระหว่างไฟล์ดัมพ์ 2 ด้วยคำสั่ง diff

    grep 'foo' *.log | cut -c1-14 | uniq > txt1.txt
    grep * *.log | cut -c1-14 | uniq > txt2.txt
    diff txt1.txt txt2.txt | grep ">"
    

ฉันลืมคำสั่ง แต่แทนที่จะทิ้งชื่อไฟล์คุณสามารถทำได้จริง ๆdiffระหว่างสองสตรีมเอาท์พุท (ฉันคิดว่าคุณล้อมรอบคำสั่งด้วยวงเล็บและมีวงเล็บมุมอยู่ตรงนั้นด้วย) หากระบบของคุณรองรับซึ่งฉันเดา เป็นคำถามเพราะมันไม่สนับสนุนgrep -L
Dexygen

1

find *20161109* -mtime -2|grep -vwE "(TRIGGER)"

คุณสามารถระบุตัวกรองภายใต้ "ค้นหา" และสตริงการยกเว้นภายใต้ "grep -vwE" ใช้ mtime under find หากคุณต้องการกรองเวลาที่แก้ไขด้วย


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

1

เปิดรายงานข้อผิดพลาด

ตามที่แสดงความคิดเห็นโดย @tukan มีรายงานข้อผิดพลาดแบบเปิดสำหรับ Ag เกี่ยวกับ-L/ --files-without-matchesflag:

เนื่องจากมีความคืบหน้าเล็กน้อยในการรายงานข้อผิดพลาด-Lตัวเลือกที่กล่าวถึงด้านล่างไม่ควรเชื่อถือได้และตราบใดที่ข้อผิดพลาดยังไม่ได้รับการแก้ไข ใช้วิธีการต่าง ๆ ที่นำเสนอในชุดข้อความนี้แทน อ้างถึงความคิดเห็นสำหรับรายงานข้อผิดพลาด [highlight mine]:

มีการอัพเดทอะไรบ้าง? -Lละเว้นการจับคู่ในบรรทัดแรกของไฟล์อย่างสมบูรณ์ ดูเหมือนว่าถ้าสิ่งนี้จะไม่ได้รับการแก้ไขในไม่ช้าธงควรจะถูกลบออกทั้งหมดเนื่องจากจะไม่สามารถทำงานได้อย่างมีประสิทธิภาพตามที่โฆษณาไว้เลย


The Silver Searcher - Ag (ฟังก์ชันที่ตั้งใจ - ดูรายงานข้อผิดพลาด)

ในฐานะทางเลือกที่ทรงพลังgrepคุณสามารถใช้The Silver Searcher - Ag :

เครื่องมือค้นหารหัสที่คล้ายกับแอ๊โดยมุ่งเน้นที่ความเร็ว

มองไปที่man agเราพบ-Lหรือ--files-without-matchesตัวเลือก:

...

OPTIONS
    ...

    -L --files-without-matches
           Only print the names of files that don´t contain matches.

คือค้นหาไฟล์ที่ไม่ตรงกันซ้ำfooๆ จากไดเรกทอรีปัจจุบัน:

ag -L foo

หากต้องการค้นหาเฉพาะไดเรกทอรีปัจจุบันสำหรับไฟล์ที่ไม่ตรงกันfooเพียงระบุ--depth=0การสอบถามซ้ำ:

ag -L foo --depth 0

สิ่งนี้ล้มเหลวเป็นครั้งคราวเนื่องจาก-Lข้อผิดพลาด - github.com/ggreer/the_silver_searcher/issues/238
tukan

@tukan ขอบคุณสำหรับพรอมต์ ฉันได้อัพเดตคำตอบแล้ว เลือกที่จะไม่ลบคำตอบ แต่เปิดด้วยข้อมูลที่เกี่ยวข้องกับข้อผิดพลาด
dfri

1

อีกทางเลือกหนึ่งเมื่อ grep ไม่มีตัวเลือก -L (ตัวอย่างเช่น IBM AIX) โดยไม่มีอะไรยกเว้น grep และเชลล์:

for file in * ; do grep -q 'my_pattern' $file || echo $file ; done

-4
grep -irnw "filepath" -ve "pattern"

หรือ

grep -ve "pattern" < file

คำสั่งด้านบนจะให้ผลลัพธ์กับเราเมื่อ -v ค้นหาส่วนผกผันของรูปแบบที่ถูกค้นหา


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

คำสั่งที่คุณระบุรายการไฟล์ใน "filepath" พร้อมบรรทัดทั้งหมดที่ไม่มี "pattern"
aprodan

-6

คำสั่งต่อไปนี้สามารถช่วยคุณกรองบรรทัดที่มีซับสตริง "foo"

cat file | grep -v "foo"

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