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/barfoo/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-pathfind
ระวังว่ามันจะไม่ผิดพลาด 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อย่างไร