ลบไฟล์และไดเรกทอรีด้วยชื่อ ไม่พบไฟล์หรือโฟลเดอร์ที่คุณค้นหา


32

ฉันต้องการลบข้อมูลที่รวบรวมทั้งหมด:

  • ไดเรกทอรีที่เรียกว่าbuild,
  • ไดเรกทอรีที่เรียกว่าobj,
  • ไฟล์ * .so

ฉันเขียนคำสั่ง

find \( -name build -o -name obj -o -name *.so \) -exec rm -rf {} \;

ที่ผ่านไดเรกทอรีทั้งหมดซ้ำและลบทั้งหมดที่ฉันต้องการ

ทำไมฉันถึงมีผลลัพธ์เช่นนี้ในตอนท้าย? บางทีฉันควรเขียนคำสั่งอื่น

find: `./3/obj': No such file or directory
find: `./3/build': No such file or directory
find: `./1/obj': No such file or directory
find: `./1/build': No such file or directory
find: `./2/obj': No such file or directory
find: `./2/build': No such file or directory

คุณเป็นระบบอะไร คุณควรใช้findเช่นนี้find /search_directory optionsละเว้นไดเรกทอรีการค้นหาไม่ใช่ความคิดที่ดี
Kiwy

การลบอัตโนมัติเช่นนี้เป็นความคิดที่ไม่ดี คุณอาจมีสคริปต์ให้ผู้สมัครซึ่งคุณควรดูเพื่อให้แน่ใจว่าคุณไม่ได้ลบสิ่งที่สำคัญหรือจำเป็นสำหรับระบบ คุณไม่ชัดเจนว่าคุณกำลังใช้งานที่ใด หากคุณเพียงแค่ทำสิ่งนี้ในพื้นที่ผู้ใช้ฉันคิดว่ามันไม่สามารถทำอันตรายได้มาก แต่คุณควรตรวจสอบให้แน่ใจว่าคุณไม่ได้ทำสิ่งนี้ในพื้นที่ระบบโดยไม่ตั้งใจ แน่นอนคุณต้องการเรียกใช้สคริปต์ในฐานะผู้ใช้
Faheem Mitha

@ Kiwy, @ FaheemMitha คำสั่งจะใช้ในโครงการ directoty เท่านั้น มันจะไม่ทำอันตรายใด ๆ ที่นั่น
Maksim Dmitriev

คำตอบ:


54

ใช้-pruneในไดเรกทอรีที่คุณจะลบต่อไปเพื่อบอกว่าfindไม่ต้องพยายามค้นหาไฟล์ใน:

find . \( -name build -o -name obj -o -name '*.so' \) -prune -exec rm -rf {} +

นอกจากนี้โปรดทราบว่า*.soจะต้องมีการเสนอราคาเป็นอย่างอื่นเปลือกอาจจะขยายไปยังรายการของ.soไฟล์ในไดเรกทอรีปัจจุบัน

สิ่งที่เทียบเท่ากับ GNU ของคุณ-regexคือ:

find . \( -name build -o -name obj -o -name '*?.so' \) -prune -exec rm -rf {} +

โปรดทราบว่าหากคุณจะใช้ไวยากรณ์เฉพาะของ GNU คุณอาจใช้-deleteแทน-exec rm -rf {} +เช่นกัน ด้วย-deleteGNU findจะเปิด-depthโดยอัตโนมัติ มันไม่เรียกใช้คำสั่งภายนอกดังนั้นวิธีนั้นจะมีประสิทธิภาพมากกว่าและปลอดภัยกว่าเนื่องจากลบเงื่อนไขการแข่งขันที่บางคนอาจทำให้คุณลบไฟล์ที่ไม่ถูกต้องโดยเปลี่ยนไดเรกทอรีเป็น symlink ในระหว่างเวลาfindค้นหาไฟล์และrmลบออก (ดูinfo -f find -n 'Security Considerations for find'รายละเอียด)

find . -regextype posix-egrep -regex '.*/((obj|build)(/.*)?|.+\.so)' -delete

-deleteนอกจากนี้ยังจัดการสิ่งต่างๆเช่นช่องว่างที่ดีกว่า
Izkata

@ อิซกะตะไม่ดีไปกว่า-exec rm -rf {} +สิ่งที่ไม่มีปัญหากับสิ่งเหล่านั้น
Stéphane Chazelas

@StephaneChazelas - ฉันสับสน{}- ควรอ้างอิงหรือไม่ ดูเหมือนว่าจะทำงานโดยไม่มีเครื่องหมายคำพูด แต่GNU Findutils Manualใช้'{}'ในตัวอย่าง คุณช่วยอธิบายได้ไหม?
grebneke

1
@grebneke ฉันคิดว่ามีโพสต์บางแห่งที่อ้างว่าราคาอาจจำเป็นต้องใช้ในรุ่นเก่ามากcshแต่ฉันไม่สามารถตรวจสอบการเรียกร้องที่ พวกมันไม่จำเป็นในเปลือกหอยสมัยใหม่ที่ฉันรู้ พวกเขาไม่ต้องการ POSIX แน่นอน ตัวอย่าง POSIXไม่ใช้พวกเขา
Stéphane Chazelas

3
และ-deleteไม่สามารถใช้กับไดเรกทอรีได้
St0rM

8

ฉันเดาเหตุผลก็คือfindลบทรีไดเรกทอรีก่อนและพยายามตรวจสอบเนื้อหาไดเรกทอรีซึ่งเห็นได้ชัดว่าไม่ใช่ลำดับที่ดีที่สุด คุณสามารถบังคับfindให้ตรวจสอบเนื้อหาก่อน:

find . -depth ...

คุณควรพิจารณาใช้-deleteไฟล์และ-exec rmdirไดเรกทอรี


0

ทางออกของฉัน

find . -regextype posix-egrep -regex ".*/(obj|build|.+\.so)" -prune -exec rm -rf {} +

+ vs \; ในคำสั่ง -exec


นั่นไม่ใช่การทำงานตลอดเวลาหากไม่มีขอบเขตระหว่างการประมวลผลเกิดขึ้นภายในไดเรกทอรีที่ถูกลบ
Gilles 'หยุดชั่วร้าย'

@Gilles "ขอบเขตระหว่างการประหารชีวิต" หมายความว่าอะไร?
Maksim Dmitriev

1
-exec … {} +เรียกใช้งานคำสั่งสำหรับหลายไฟล์พร้อมกันให้มากที่สุดเท่าที่พอดีกับบรรทัดคำสั่ง หากมีไฟล์มากเกินไป (หรือมากกว่านั้นหากความยาวรวมของพา ธ ยาวเกินไป) findจะดำเนินการหลายอินสแตนซ์rmซึ่งอาจสิ้นสุดการลบไดเรกทอรีที่มีการสำรวจเส้นทาง มันมีโอกาสน้อย+กว่าด้วย;แต่+ไม่ได้แก้ปัญหา
Gilles 'ดังนั้น - หยุดความชั่วร้าย'
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.