fooฉันต้องการที่จะลบไฟล์ทั้งหมดที่มีสตริง ฉันจะทำสิ่งนี้โดยใช้ bash ใน Linux ได้อย่างไร
foo(เช่นmyfoo.jpg) หรือไฟล์ที่มีลำดับไบต์foo(ซึ่งอาจรวมถึงไฟล์ไบนารีที่เกิดขึ้นเพื่อให้มีลำดับไบต์นั้น)
fooฉันต้องการที่จะลบไฟล์ทั้งหมดที่มีสตริง ฉันจะทำสิ่งนี้โดยใช้ bash ใน Linux ได้อย่างไร
foo(เช่นmyfoo.jpg) หรือไฟล์ที่มีลำดับไบต์foo(ซึ่งอาจรวมถึงไฟล์ไบนารีที่เกิดขึ้นเพื่อให้มีลำดับไบต์นั้น)
คำตอบ:
นี่คือวิธีที่ปลอดภัย:
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แยกออกจากกันที่ช่องว่างเมื่อมีการตีความ การใส่รายชื่อไฟล์ลงในตัวแปรสเกลาร์เชลล์เป็นสิ่งที่อันตราย
$ 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
find -type f -exec grep -q 'foo' {} \; -delete(เครื่องหมายคำพูดรอบ ๆ{}ซ้ำซ้อนfindสามารถลบไฟล์ได้ด้วย) โปรดทราบว่าgrepยอมรับการแสดงออกปกติ หากคุณต้องการค้นหาให้foo.barหลีกเลี่ยงสิ่งนี้หรือส่ง-Fตัวเลือกเพื่อรักษารูปแบบตามตัวอักษร
-exec echo rm "{}" \;และไม่-delete?
-deleteไม่ฉันต้องการใช้ มันง่ายกว่าที่จะสาธิตด้วยเสียงที่สอง-execและสะท้อนเสียง
-print(หรือสำหรับฟุ่มเฟื่อยมากขึ้นกว่า)-ls -exec echo rm "{}" \'ไม่จำเป็นต้องมียูทิลิตี้ภายนอก
ฉันจะทำสิ่งที่เอเดรียนพูด
แต่ฉันจะเพิ่มขอบเขตของคำเพื่อไม่ให้ลบไฟล์ที่มีคำว่า "อาหาร" (เว้นแต่จะเป็นการลบทุกอย่างที่มีอาหารเป็นสิ่งที่คุณต้องการ)
$ find -type f -exec grep -q "\<foo\>" {} \; -delete
ฉันจะเปลี่ยนเส้นทางผลลัพธ์ก่อนที่จะลบดังนั้นฉันสามารถตรวจสอบก่อนที่จะลบ:
$ find -type f -exec grep -q "\<foo\>" > /tmp/list_of_files_to_delete