เพราะเหตุใดค้นหาด้วย -delete ลบไฟล์ในไดเรกทอรี / save / ของฉันเมื่อค้นหาโดยไม่ลบไม่สามารถค้นหาได้


20

saveฉันต้องการที่จะลบไฟล์ทั้งหมดที่อยู่ในต้นไม้ไดเรกทอรีปัจจุบันยกเว้นผู้ที่อยู่ใน ฉันรันคำสั่งนี้:

 find . \( -name save -prune \) -o -type f -ls | grep /save/

และไม่พบเลย แต่เมื่อฉันรันคำสั่งนี้:

 find . \( -name save -prune \) -o -type f -delete

ไฟล์เหล่านั้นทั้งหมดใน / บันทึก / หายไป ฉันพลาดอะไรไป


4
อุ๊ย ... ฉันเรียนรู้บางอย่างวันนี้ (ขอบคุณคุณ) และฉันขอแนะนำวิธีง่าย ๆmv save/ ../some/safer/locationก่อนหน้าคำสั่งลบ "ทั่วไป" (... แต่แน่นอนก่อนที่จะโพสต์ของคุณฉันได้ทำการตรวจสอบแบบเดียวกันและพบปัญหาเดียวกัน!) ตอนนี้ไปหา "ยกเลิกการลบ" ที่ดีสำหรับระบบไฟล์ที่ไฟล์อยู่ ^^
Olivier Dulac

3
ความเจ็บปวดของฉันคือการป้องกันของคุณ
Otheus

1
1,000 ขอบคุณสำหรับคุณ รหัส (มัก) ทำงานในรูปแบบลึกลับ ...
โอลิเวีย Dulac

3
เกี่ยวข้อง: unix.stackexchange.com/questions/87258/…
lesmana

@lesmana ฉัน upvoted คำตอบของคุณที่นั่น เศร้ารุ่นของฉันหาไม่ให้ฉันเช่นคำเตือนที่ดี :(
Otheus

คำตอบ:


26

-deleteบอกเป็นนัย ๆ-depthว่าใช้ไม่ได้กับ-prune( -depthเริ่มต้นด้วยใบไม้) มีคำเตือนเกี่ยวกับสิ่งนั้นในคู่มือของ GNU เวอร์ชัน ( -deleteเป็นส่วนขยาย FreeBSD ตอนนี้ยังรองรับโดย GNU findและการใช้งานอื่น ๆ สองสาม)

info find --index-search=-delete

การใช้การกระทำ '-delete' บนบรรทัดคำสั่งจะเปิดตัวเลือก '-depth' โดยอัตโนมัติ (* note find Expressions: :) สิ่งนี้อาจน่าประหลาดใจหากก่อนหน้านี้คุณเพิ่งทดสอบด้วย '-print' ดังนั้นจึงควรจำไว้ว่าให้ใช้ '-depth' อย่างชัดเจน

info find --index-search=-prune

เนื่องจาก '-delete' หมายถึง '-depth' การใช้ '-prune' ร่วมกับ '-delete' อาจส่งผลให้มีการลบไฟล์มากกว่าที่คุณตั้งใจ

ที่นี่คุณมีตัวเลือกในการใช้งานrmแทน:

find . -name save -prune -o -type f -exec rm -f {} +

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

ทางเลือกที่ปลอดภัยกว่า:

find . -name save -prune -o -type f -execdir rm -f -- {} \;

ไม่ได้มีปัญหาดังกล่าวข้างต้น แต่หมายถึงการทำงานอย่างใดอย่างหนึ่งrmต่อไฟล์ --เป็นสิ่งที่จำเป็นสำหรับการดำเนินงาน FreeBSD ไม่ GNU ./หนึ่งที่นำหน้าชื่อไฟล์ที่มี

อีกทางหนึ่งตามที่ Costas แนะนำ:

LC_ALL=C find . ! -name save ! -path '*/save/*' -type f -delete

(แต่ยังไม่จำเป็นต้องสืบทอดลงในsaveไดเรกทอรี)

LC_ALL=Cมีเพื่อให้*ตรงกับลำดับใด ๆ ของไบต์ (แม้กระทั่งผู้ที่ไม่ได้แบบตัวอักษรที่ถูกต้องในสถานที่ปัจจุบัน) โปรดทราบว่าจะมีผลกับภาษาของข้อความแสดงข้อผิดพลาด (ภาษาอังกฤษแทนที่จะเป็นภาษาของผู้ใช้)


ปัญหาด้านความปลอดภัยที่นี่rmคืออะไร
jrw32982 รองรับ Monica

@ jrw32982, ดูการแก้ไขพร้อมลิงก์ไปยัง GNU find manual
Stéphane Chazelas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.