ฉันต้องการที่จะหาไฟล์ที่มีสองสายร่วมกันเช่นไฟล์มีทั้งและstring1string2
ฉันต้องการเส้นทางแบบเต็มของไฟล์ที่ส่งออก ฉันไม่ต้องการเห็นคำเตือน "การปฏิเสธสิทธิ์"
ฉันต้องการที่จะหาไฟล์ที่มีสองสายร่วมกันเช่นไฟล์มีทั้งและstring1string2
ฉันต้องการเส้นทางแบบเต็มของไฟล์ที่ส่งออก ฉันไม่ต้องการเห็นคำเตือน "การปฏิเสธสิทธิ์"
คำตอบ:
grep -l string2 `grep -l string1 /path/*`
ซึ่งเหมือนกับ
grep -l string2 $(grep -l string1 /path/*)
แก้ไข: นี่คือเหตุผลที่grep string1 /path/* | grep string2ไม่ได้ทำในสิ่งที่ฉันคิดว่า alwbtc ต้องการ
$ cd /tmp
$ cat a
apples
oranges
bananas
$ cat b
apples
mangoes
lemons
$ cat c
mangoes
limes
pears
$ cd ~
$ grep apples /tmp/* | grep mangoes
$
ไม่พบอะไรเลย แต่ไฟล์ b มีทั้งสองสตริง
นี่คือสิ่งที่ฉันคิดว่า alwbtc ต้องการ
$ grep -l apples $(grep -l mangoes /tmp/*)
/tmp/b
-lตัวเลือกสำหรับทั้งสองคำสั่งให้ถือว่าเท่ากัน
ท่อหนึ่งgrepเข้าด้วยกัน:
grep "string1" /path/to/files/* | grep "string2"
ที่นี่เทียบเท่า แอ๊กชั่นคำสั่งให้คำตอบของ RedGrittyBrick :
ack string2 $(ack string1 -l)
ทำงานในลักษณะเดียวกัน (ยกเว้นackโดยค่าเริ่มต้นค้นหาไดเรกทอรีปัจจุบันซ้ำ) เนื้อหาภายในการ$()ค้นหาstring1แต่-lส่งออกเฉพาะชื่อไฟล์ที่พบสตริงนั้น พวกเขาจะถูกส่งผ่านเป็นข้อโต้แย้งในคำสั่งด้านนอกซึ่งหมายถึงการstring2ค้นหาภายในรายการของไฟล์เหล่านั้นเท่านั้น
comm -12 <(grep --fixed-strings --files-with-matches "STRING1" /path/to/files/* 2>/dev/null | sort) <(grep --fixed-strings --files-with-matches "STRING1" /path/to/files/* 2>/dev/null | sort)
หรือน้อยกว่าซ้ำซ้อน:
search_files () { str="$1"; shift; grep -Fl "$str" "$@" 2>/dev/null | sort; }
comm -12 <(search_files "STRING1" /path/to/files/*) <(sf "STRING2" /path/to/files/*)
สิ่งนี้จะทำงานหากสตริงอยู่ในบรรทัดที่แตกต่างกันของไฟล์เดียวกันและจะหลีกเลี่ยงผลบวกปลอมหากชื่อไฟล์มีหนึ่งในสตริง
หากต้องการอธิบายรายละเอียดเกี่ยวกับโซลูชันของ @ RedGrittyBrick ซึ่งมีข้อบกพร่องเมื่อรันคำสั่งแบบไม่ต้องใส่ข้อมูลบวกเพื่อระงับเอาต์พุตข้อผิดพลาดตามที่ต้องการและเพื่อค้นหาไฟล์แบบเรียกซ้ำคุณอาจพิจารณา
grep -l 'STRING1' $(! grep -lrs 'STRING2' /absolute/path/to/search/dir && echo /dev/null)
-sตัวเลือกจะระงับ
-rตัวเลือกข้อความผิดพลาดช่วยให้การค้นหาสตริงในไดเรกทอรีที่ซ้อนกันโดยพลการ
!รวมกับ&& echo /dev/nullการรับประกันว่าคำสั่งจะไม่วางสาย มิฉะนั้นหากinner grepไฟล์ไม่พบไฟล์ใด ๆ มันจะไม่แสดงผลใด ๆ ดังนั้นไฟล์outer grepจะรอให้อินพุตทำการค้นหาโดยไม่มีกำหนด โซลูชันนี้ให้ผลลัพธ์/dev/nullในกรณีเหล่านี้ดังนั้นouter grepจะค้นหาSTRING1ใน/dev/nullตำแหน่งที่ไม่ควรค้นหาสิ่งใด
ฉันกำลังมองหาวิธีที่สามารถขยายได้เพื่อทำสายอักขระ2 ตัวขึ้นไปและเกิดขึ้นกับสิ่งนี้:
grep -rl string1 path-to-files | xargs grep -l string2 | xargs grep -l string3
grep แรกจะค้นหาชื่อไฟล์ซ้ำstring1ภายในpath-to-files
ผลที่จะได้เข้าไปประปาxargsซึ่งจะทำงานอย่างใดอย่างหนึ่งหรือ grep string2เพิ่มเติมคำสั่งเกี่ยวกับไฟล์เหล่านั้น
ผลลัพธ์จะถูกไพพ์ไปยังxargsคำสั่งอื่นสำหรับstring3- เหมือนกับการxargsโทรครั้งแรกแต่ค้นหาสตริงอื่น
การใช้xargsจะหลีกเลี่ยงปัญหาที่มีผลลัพธ์จำนวนมากที่บรรทัดคำสั่งผลลัพธ์จากการใช้เครื่องหมายขีดหลังยาวเกินไป
เพื่อหลีกเลี่ยงคำเตือนเราสามารถเปลี่ยนเส้นทางstderrไปที่/dev/null:
grep -rl string1 path-to-files 2>/dev/null | xargs grep -l string2
ไม่จำเป็นสำหรับการเรียก grep ครั้งต่อไปเนื่องจากstring1พบในไฟล์แล้วดังนั้นการอนุญาตจึงเป็นสิ่งที่ดี
-lตัวเลือกเพื่อส่งคืนชื่อไฟล์แทนที่จะเป็นบรรทัด จากนั้นเขาก็ใช้เครื่องหมายดอลลาร์หรือเครื่องหมายคำพูดด้านหลังเพื่อส่งผ่านรายการนั้นเป็นFILEอาร์กิวเมนต์ใน grep ตัวที่สอง วิธีนี้ช่วยให้ grep ตัวที่สองสามารถค้นหาไฟล์ทั้งหมดที่พบแทนแต่ละบรรทัดเช่นเดียวกับในโซลูชันของฉัน