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


17

fooฉันต้องการที่จะลบไฟล์ทั้งหมดที่มีสตริง ฉันจะทำสิ่งนี้โดยใช้ bash ใน Linux ได้อย่างไร


สตริงนั้นคือชื่อไฟล์
rɑːdʒɑ

3
กรุณาชี้แจง: คุณต้องการลบไฟล์ที่มีชื่อประกอบด้วยfoo(เช่นmyfoo.jpg) หรือไฟล์ที่มีลำดับไบต์foo(ซึ่งอาจรวมถึงไฟล์ไบนารีที่เกิดขึ้นเพื่อให้มีลำดับไบต์นั้น)
hammar

คำตอบ:


33

นี่คือวิธีที่ปลอดภัย:

grep -lrIZ foo . | xargs -0 rm -f --
  • -l พิมพ์ชื่อไฟล์ของไฟล์ที่ตรงกับรูปแบบการค้นหา
  • -rดำเนินการค้นหา recursive สำหรับรูปแบบในไดเรกทอรีที่กำหนดfoo หากยังไม่สามารถทำงานให้ลอง.-R
  • -I(ตัวพิมพ์ใหญ่i) ทำให้ไฟล์ไบนารีเช่น PDF ถูกข้าม
  • -Z ตรวจสอบให้แน่ใจว่าชื่อไฟล์เป็นศูนย์ - (เช่น nul-) ถูกยกเลิกเพื่อให้ชื่อที่มี white space ไม่ได้รับการตีความในทางที่ผิด (เช่นเป็นชื่อหลาย ๆ ชื่อแทนที่จะเป็นชื่อเดียว)
  • xargs -0ฟีดชื่อไฟล์จากgrepถึงrm -fโดยแยกคำด้วยศูนย์ (nul) ไบต์ (จำ-Zตัวเลือกจากgrep)
  • --มักจะถูกลืม -แต่มันก็เป็นสิ่งที่สำคัญมากในการทำเครื่องหมายจุดสิ้นสุดของตัวเลือกและอนุญาตให้มีการกำจัดของไฟล์ที่มีชื่อขึ้นต้นด้วย

หากคุณต้องการที่จะเห็นไฟล์ที่กำลังจะถูกลบออกเพียงแค่เอา| xargs -0 rm -f --ส่วนหนึ่งและปล่อยให้ปิดตัวเลือกในการZgrep

ผู้ใช้รายอื่นแนะนำสิ่งต่อไปนี้ซึ่งคุณไม่ควรเรียกใช้เพราะไม่ปลอดภัย:

files=`grep foo * | cut -d: -f1`
rm -f $files         # unsafe, do not run it!

หากฉันมีไฟล์ImportantStuffที่ฉันไม่ต้องการลบและobsolete ImportantStuffมีอยู่fooฉันจะสูญเสียImportantStuff(และไม่ obsolete ImportantStuff !) เมื่อฉันเรียกใช้คำสั่งนี้เพราะ$filesแยกออกจากกันที่ช่องว่างเมื่อมีการตีความ การใส่รายชื่อไฟล์ลงในตัวแปรสเกลาร์เชลล์เป็นสิ่งที่อันตราย


17
$ find -type f -exec grep -q "foo" {} \; -exec echo rm -- {} \;

วิธีนี้จะค้นหาไฟล์ที่มีfooซ้ำ ๆ ที่สอง-execจะทำงานก็ต่อเมื่อการexecออกครั้งแรกประสบความสำเร็จเช่นถ้าgrepตรงกัน Dryrun และลบechoถ้าผลลัพธ์ดูเหมือนว่าถูกต้อง

หรืออีกวิธีหนึ่ง

$ find -type f -exec grep -q "foo" {} \; -print

และ

$ find -type f -exec grep -q "foo" {} \; -delete

ตามที่แนะนำโดย Lekensteyn


4
... ซึ่งสามารถย่อให้เหลือ: find -type f -exec grep -q 'foo' {} \; -delete(เครื่องหมายคำพูดรอบ ๆ{}ซ้ำซ้อนfindสามารถลบไฟล์ได้ด้วย) โปรดทราบว่าgrepยอมรับการแสดงออกปกติ หากคุณต้องการค้นหาให้foo.barหลีกเลี่ยงสิ่งนี้หรือส่ง-Fตัวเลือกเพื่อรักษารูปแบบตามตัวอักษร
Lekensteyn

เหตุผลใดที่จะใช้-exec echo rm "{}" \;และไม่-delete?
vartec

1
@vartec -deleteไม่ฉันต้องการใช้ มันง่ายกว่าที่จะสาธิตด้วยเสียงที่สอง-execและสะท้อนเสียง
Adrian Frühwirth

1
มันง่ายที่จะประเภท-print(หรือสำหรับฟุ่มเฟื่อยมากขึ้นกว่า)-ls -exec echo rm "{}" \'ไม่จำเป็นต้องมียูทิลิตี้ภายนอก
Lekensteyn

1
หากคุณใช้ rm {} ให้ใช้ rm - {} เพื่อให้อักขระพิเศษใด ๆ ในชื่อไฟล์นั้นไม่ได้รับการแก้ไข ตัวอย่างเช่นแตะ '-rf /' ในไดเรกทอรีใด ๆ ที่คุณมีสิทธิ์เขียน ...
atk

1

ฉันจะทำสิ่งที่เอเดรียนพูด

แต่ฉันจะเพิ่มขอบเขตของคำเพื่อไม่ให้ลบไฟล์ที่มีคำว่า "อาหาร" (เว้นแต่จะเป็นการลบทุกอย่างที่มีอาหารเป็นสิ่งที่คุณต้องการ)

 $ find -type f -exec grep -q "\<foo\>" {} \; -delete

ฉันจะเปลี่ยนเส้นทางผลลัพธ์ก่อนที่จะลบดังนั้นฉันสามารถตรวจสอบก่อนที่จะลบ:

 $ find -type f -exec grep -q "\<foo\>" > /tmp/list_of_files_to_delete

ทันทีที่คุณสามารถโพสต์ความคิดเห็นได้คุณควรโพสต์สิ่งต่าง ๆ เช่นนั้นเป็นความคิดเห็น
FSMaxB

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