TL; DR: วิธีที่ดีที่สุดคือการใช้แทน-exec rm
-delete
find a \( -name b -prune \) -o -type f -exec rm {} +
คำอธิบาย:
ทำไมถึงพบบ่นเมื่อคุณพยายามที่จะใช้-delete
กับ-prune
?
คำตอบสั้น ๆ : เพราะ-delete
หมายถึง-depth
และ-depth
ทำให้-prune
ไม่มีประสิทธิภาพ
ก่อนที่เราจะมาถึงคำตอบที่ยาวนานก่อนอื่นให้สังเกตพฤติกรรมของการค้นหาที่มีและไม่มี-depth
:
$ find foo/
foo/
foo/f1
foo/bar
foo/bar/b2
foo/bar/b1
foo/f2
ไม่มีการรับประกันเกี่ยวกับการสั่งซื้อในไดเรกทอรีเดียว แต่มีการรับประกันว่าไดเรกทอรีจะถูกประมวลผลก่อนเนื้อหา หมายเหตุfoo/
ก่อนfoo/*
และก่อนที่จะfoo/bar
foo/bar/*
-depth
นี้สามารถกลับด้วย
$ find foo/ -depth
foo/f2
foo/bar/b2
foo/bar/b1
foo/bar
foo/f1
foo/
โปรดทราบว่าตอนนี้สิ่งที่ปรากฏก่อนfoo/*
เช่นเดียวกันกับfoo/
foo/bar
คำตอบอีกต่อไป:
-prune
ป้องกันการค้นหาจากมากไปน้อยในไดเรกทอรี ในคำอื่น ๆ-prune
ข้ามเนื้อหาของไดเรกทอรี ในกรณีของคุณ-name b -prune
ป้องกันหาได้จากมากไปหาน้อยลงในไดเรกทอรีใด ๆ b
ที่มีชื่อ
-depth
ทำให้ค้นหาเพื่อประมวลผลเนื้อหาของไดเรกทอรีก่อนไดเรกทอรีเอง ซึ่งหมายความว่าเมื่อถึงเวลาที่ได้รับการประมวลผลรายการไดเรกทอรีb
เนื้อหาที่ได้รับการประมวลผลแล้ว ดังนั้นจึง-prune
ไม่ได้-depth
ผล
-delete
แสดงนัย-depth
เพื่อให้สามารถลบไฟล์ก่อนแล้วจึงไปยังไดเรกทอรีว่าง -delete
ปฏิเสธที่จะลบไดเรกทอรีที่ไม่ว่างเปล่า ผมคิดว่ามันจะเป็นไปได้ที่จะเพิ่มตัวเลือกที่จะบังคับให้-delete
ลบไดเรกทอรีที่ไม่ว่างเปล่าและ / หรือเพื่อป้องกันการที่จะบ่งบอก-delete
-depth
แต่นั่นเป็นอีกเรื่องหนึ่ง
มีวิธีอื่นในการบรรลุสิ่งที่คุณต้องการ:
find a -not -path "*/b*" -type f -delete
สิ่งนี้อาจจะใช่หรือไม่ใช่จดจำได้ง่ายกว่า
คำสั่งนี้ยังคงสืบทอดไปยังไดเรกทอรีb
และประมวลผลทุกไฟล์ในนั้นเพียง-not
เพื่อปฏิเสธพวกเขา นี่อาจเป็นปัญหาด้านประสิทธิภาพหากไดเรกทอรีb
มีขนาดใหญ่
-path
-name
การทำงานที่แตกต่างกว่า -name
จับคู่กับชื่อ (ของไฟล์หรือไดเรกทอรี) เท่านั้นขณะที่-path
จับคู่กับพา ธ ทั้งหมด /home/lesmana/foo/bar
ยกตัวอย่างเช่นสังเกตเส้นทาง เพราะจะตรงกับชื่อเป็น-name -bar
จะจับคู่เพราะสตริงอยู่ในเส้นทาง มีความซับซ้อนที่คุณควรเข้าใจก่อนใช้งาน อ่าน man page ของสำหรับรายละเอียดเพิ่มเติมbar
-path "*/foo*"
/foo
-path
find
ระวังว่ามันจะไม่ผิดพลาด 100% มีโอกาสของ "การบวกเท็จ" วิธีที่คำสั่งถูกเขียนไว้ด้านบนมันจะข้ามไฟล์ใด ๆ ที่มีไดเรกทอรีหลักที่ชื่อเริ่มต้นด้วยb
(บวก) แต่มันจะข้ามไฟล์ใด ๆ ที่ชื่อขึ้นต้นด้วยb
โดยไม่คำนึงถึงตำแหน่งในทรี (false positive) "*/b*"
นี้สามารถแก้ไขได้โดยการเขียนการแสดงออกที่ดีกว่า ที่เหลือเป็นแบบฝึกหัดสำหรับผู้อ่าน
ฉันคิดว่าคุณใช้a
และb
เป็นตัวยึดตำแหน่งและชื่อจริงมีลักษณะเหมือนallosaurus
และbrachiosaurus
มากกว่า หากคุณใส่brachiosaurus
ในสถานที่ของb
แล้วจำนวนบวกเท็จจะลดลงอย่างเห็นได้ชัด
อย่างน้อยผลบวกปลอมจะไม่ถูกลบดังนั้นจึงไม่เป็นเรื่องน่าเศร้า นอกจากนี้คุณสามารถตรวจสอบผลบวกผิดพลาดโดยเรียกใช้คำสั่งแรกโดยไม่ต้อง-delete
(แต่อย่าลืมวางนัย-depth
) และตรวจสอบผลลัพธ์
find a -not -path "*/b*" -type f -depth
a
ยกเว้นa/b
อย่างไร