ฉันจะลบไดเรกทอรีย่อยทั้งหมดออกจากภายในไดเรกทอรีได้อย่างไร


51

คำถามนี้เป็นเฟสที่สองของคำถามแรกที่ฉันโพสต์ที่นี่

ฉันมีไดเรกทอรีที่มีกลุ่มของไดเรกทอรีย่อยไฟล์. zip และไฟล์สุ่มอื่น ๆ ที่ไม่อยู่ในไดเรกทอรีย่อย

ฉันต้องการสคริปต์บรรทัดคำสั่งเพื่อลบไดเรกทอรีย่อยทั้งหมดออกจากภายในไดเรกทอรีหลัก แต่เก็บไฟล์ zip และไฟล์ทั้งหมดที่ไม่ได้อยู่ในไดเรกทอรีย่อยใด ๆ ไดเรกทอรีย่อยทั้งหมดมีเนื้อหาดังนั้นฉันเชื่อว่าฉันต้องบังคับให้ลบด้วยคำสั่ง -f

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

ฉันเข้าใจว่าการลบรายการออกจากบรรทัดคำสั่งจำเป็นต้องได้รับการดูแลเป็นพิเศษ แต่ฉันได้ใช้ความระมัดระวังที่จำเป็นทั้งหมดแล้วในการสำรองข้อมูลจากระยะไกล

คำตอบ:


61

ใน BASH คุณสามารถใช้เครื่องหมายทับท้าย (ฉันคิดว่ามันควรจะทำงานใน POSIX เชลล์):

rm -R -- */

โปรดสังเกต--ว่าตัวเลือกใดที่แยกตัวออกจากข้อโต้แย้งและอนุญาตให้รายการหนึ่งเอารายการที่เริ่มต้นด้วยยัติภังค์ - มิฉะนั้นหลังจากการขยายโดยเชลล์ชื่อรายการจะถูกตีความว่าเป็นตัวเลือกโดยrm(ถือเหมือนกันสำหรับอรรถประโยชน์บรรทัดคำสั่งอื่น ๆ )

เพิ่ม-fตัวเลือกหากคุณไม่ต้องการให้มีการยืนยันเมื่อลบไฟล์ที่ไม่สามารถเขียนได้

โปรดทราบว่าโดยค่าเริ่มต้นไดเรกทอรีที่ซ่อนอยู่ (ที่มีชื่อขึ้นต้นด้วย.) จะถูกทิ้งไว้ตามลำพัง

ข้อแม้สำคัญ: การขยายตัวของ*/ความประสงค์ ได้แก่ symlinks ว่าในที่สุดจะแก้ไขไฟล์ประเภทไดเรกทอรี และขึ้นอยู่กับการrmใช้งานrm -R -- thelink/เพียงแค่จะลบ symlink หรือ (ในส่วนใหญ่ของพวกเขา) ลบเนื้อหาของไดเรกทอรีที่เชื่อมโยงแบบวนซ้ำ แต่ไม่ใช่ไดเรกทอรีนั้นเองหรือ symlink

หากใช้zshวิธีการที่ดีกว่าคือการใช้โปรแกรมระบุคุณสมบัติกลมเพื่อเลือกไฟล์ของไดเรกทอรีประเภทเท่านั้น:

rm -R -- *(/) # or *(D/) to include hidden ones

หรือ:

rm -R -- *(-/)

เพื่อรวม/symlink ไปยังไดเรกทอรี (แต่เนื่องจากเวลานี้การขยายไม่มี trailing s มันเป็น symlink เท่านั้นที่ถูกลบด้วยrmการใช้งานทั้งหมด)

ด้วยbash, AT & T ksh, yashหรือzshคุณสามารถทำได้:

set -- */
rm -R -- "${@%/}"

/ที่จะตัดต่อท้าย


สวย! มันทำงานได้อย่างสมบูรณ์แบบ ฉันไม่ได้ตระหนักว่ามันเป็นเรื่องง่ายที่จะทำ คุณจะช่วยอธิบายเกี่ยวกับ -r กับ -R และคำสั่งเหล่านั้นทำอะไร? ขอบคุณมาก.
Evster

-r, -R, --recursiveเป็นคำพ้องความหมาย "ลบไดเรกทอรีและเนื้อหาซ้ำ"
เตอร์

คุณสามารถอธิบายสิ่งที่ - และ * / ทำอย่างไร
สัตว์สะเทินน้ำสะเทินบก

6
คุณสามารถพูดได้rm -R ./*/- นอกจากนี้ยังช่วยหลีกเลี่ยงปัญหาเกี่ยวกับชื่อยัติภังค์
l0b0

1
เพียงระวังอย่าเปลี่ยนลำดับของ * และ / rm -R - / * ทำสิ่งที่แตกต่างอย่างสิ้นเชิงที่คุณอาจไม่ต้องการเกิดขึ้น: |
ChrisOdney

13

นอกเหนือจากวิธีการใช้สัญลักษณ์แทนคุณยังสามารถใช้find(อย่างน้อย GNU ค้นหา) เพื่อทำสิ่งนี้:

find -mindepth 1 -maxdepth 1 -type d -print0 | xargs -0 rm -R

เช่นเดียวกับfindบรรทัดอื่น ๆคุณสามารถเรียกใช้ส่วนแรก ( find -mindepth 1 -maxdepth 1 -type d) เพื่อดูรายการไดเรกทอรีที่จะถูกลบออก

ตัวเลือกที่ปลอดภัยกว่าคือการทำสิ่งนี้:

find -mindepth 1 -maxdepth 1 -type d -print0 | xargs -0 mv -i -t ../to-rm
# or
mv -i -t ../to-rm */
# or
mv -i */ ../to-rm

สิ่งใดก็ตามที่จะย้ายสิ่งของทั้งหมดไปไว้../to-rmแทนที่จะลบออก คุณสามารถตรวจสอบว่ามันทำในสิ่งที่คุณต้องการพวกเขาrm -Rfไดเรกทอรีที่พักผ่อนของคุณ


+1 สำหรับ "CLI-ถังขยะถัง" to-rmและfindซึ่งอย่างจัดการไดเรกทอรีเริ่มต้นด้วยจุด (นอกเหนือไปจากที่ยุ่งยากอื่น ๆ หลบหนี) :)
เตอร์

ขอบคุณสำหรับทิป. ฉันชอบความคิดในการย้ายไปยังไดเรกทอรีที่แยกต่างหากก่อนที่จะลบ ฉันทำงานผ่าน Terminal ใน Mac OS X และฉันเชื่อว่าฉันต้องติดตั้งแพคเกจ GNU บางประเภทเพื่อใช้คำสั่ง -mindepth และ -maxdepth ใช่ไหม?
Evster

@Evster ไม่แน่ใจว่า Mac OS X ค้นหานั้นรองรับหรือไม่ ฉันเดาว่าตำรวจ (ที่ยังอยู่รอบ ๆ ) สามารถติดตั้งการค้นหาที่ทำ หรือคุณสามารถละเว้นพวกเขาแล้วกรองรายการไฟล์ที่ผลิตโดยใช้ grep ใช้ตัวเลือก mv อย่างแน่นอนว่า istead of rm
Derobert

4

คุณอาจต้องการสร้างสคริปต์สำหรับคำแนะนำเหล่านี้โดยเฉพาะrm -R -- */และเก็บไว้ในโฟลเดอร์ / usr / local / bin ของคุณ หรือสร้างaliasในไฟล์ ~ / .bashrc ของคุณ ตั้งแต่มันเพื่อให้ง่ายต่อการพิมพ์ผิดคำสั่งและทำลายระบบของคุณ - แม้แต่ตัวอักษรเดียวและ / หรือคำสั่งของตัวอักษรที่สามารถส่งผลให้เกิดผลเป็นความหายนะ - นี้จะทำหน้าที่เป็นวิธีการแก้ปัญหาที่ค่อนข้างแข็งแกร่งมากขึ้นกว่าที่มีการพิมพ์ตัวเลือกที่แตกต่างกันและข้อโต้แย้ง ทุกครั้งที่คุณต้องการทำงานนี้ให้สำเร็จ

นอกจากนี้คุณอาจต้องการรวม-i or --interactive=onceหรือ-I or --interactive=alwaysตัวเลือกในสคริปต์ / คำสั่งของคุณซึ่งจะทำหน้าที่เป็นเครื่องมืออื่นเพื่อหลีกเลี่ยงการลบโดยไม่ตั้งใจ

นอกจากนี้สิ่งที่แนะนำเช่นDerobertจะดีที่สุด; เพียงแค่คัดลอก / วางสคริปต์ลงในไฟล์ / เทอร์มินัล - เอดิเตอร์และปรับให้เข้ากับความต้องการเฉพาะของคุณและไฟล์ / ไดเรกทอรีจะถูกย้ายไปยังไดเรกทอรีเดียว (เนื้อหาที่คุณสามารถตรวจสอบ / ตรวจสอบ) ที่คุณสามารถลบ การออกrm -rfคำสั่ง

อีกตัวเลือกหนึ่งคือการใช้แอปพลิเคชัน GUI เช่นตัวจัดการไฟล์ของคุณและเลือกไฟล์ / โฟลเดอร์ที่เกี่ยวข้องทั้งหมดที่คุณต้องการลบ ตรวจสอบหน้าคู่มือการแจกจ่ายของคุณหากคุณไม่มีสิทธิ์

ท้ายที่สุดถ้าโฟลเดอร์ว่างเปล่า - ชื่อไฟล์เป็นหลัก - คุณสามารถใช้rmdirคำสั่งเพื่อลบมันได้ มันไม่ได้ผลกับทุกสิ่งที่คุณอาจต้องการลบ แต่มันจะมีประโยชน์เมื่อคุณต้องการ "ทำความสะอาดบ้าน" ** คุณอาจต้องการลองใช้-p --ignore-fail-on-non-emptyตัวเลือกซึ่งจะช่วยให้คุณสามารถลบไดเรกทอรีย่อยบางรายการเช่นเดียวกับ "parent" ที่ว่างเปล่า - ไดเรกทอรีที่พวกเขาอาศัยอยู่


เป็นความคิดที่ดีจริงๆในการสร้างสคริปต์แยกต่างหากที่ฉันสามารถเรียกใช้สำหรับคำสั่งนี้ได้ คุณช่วยอธิบายได้ว่าตัวเลือก -i และ -I ทำอะไรได้บ้าง? ขอบคุณ!
Evster

ตัวเลือก - ฉันจะแจ้งให้คุณหนึ่งครั้งหลังจากที่คุณกด "Enter" เพื่อยืนยันว่าคุณต้องการลบนี้ (เมื่อมีมากกว่า 3 ไฟล์ / โฟลเดอร์ "เลือก"); ในขณะที่ตัวเลือก -i จะออกพรอมต์สำหรับแต่ละไฟล์ซึ่งคุณสามารถยืนยันได้โดยแตะ "y" และ "Enter" - อะไรก็ตามที่นอกเหนือจากการตอบกลับที่ยืนยันแล้วจะส่งผลให้ไฟล์นั้นถูกข้ามไปในระหว่างกระบวนการลบ
ILMostro_7

1

ก่อนอื่นคุณต้องแสดงรายการไดเรกทอรีแล้วลบออกโดยไม่ขัดขวางไฟล์ปกติ ls -d * /, แสดงรายการเฉพาะไดเรกทอรีย่อยและไปป์ด้วย rm จะลบไดเรกทอรีและเนื้อหาทำให้ไฟล์หลวมไม่เปลี่ยนแปลง

คำสั่งนี้ควรทำงาน

ls -d  */ | xargs rm -rf

1
สิ่งที่จะได้รับประโยชน์มากกว่าrm -rf -- */? printf '%s\0' */ | xargs -r0 rm -rf --จะช่วย (ในเชลล์ที่printfบิวด์อินและไม่ใช่ls) เพื่อแก้ไขรายการข้อผิดพลาดที่มีขนาดใหญ่เกินไปแต่ls -d */ | xargs rm -rfจะไม่เพิ่ม AFAICT ใด ๆ ยกเว้นปัญหาเพิ่มเติม
Stéphane Chazelas

1
@AnthonyGeoghegan ใช่เช่นถ้ามีไดเรกทอรีชื่อ" .."(ช่องว่าง..) ก็จะลบเนื้อหาของไดเรกทอรีหลักด้วยlsการใช้งานบางอย่าง และก็ไม่ได้เพียงแค่พื้นที่ก็ยังมีตัวละครอื่น ๆ -ที่ว่างเปล่าขึ้นบรรทัดใหม่คำพูดเดียวอ้างคู่ทับขวาและชื่อไฟล์ที่เริ่มต้นด้วย
Stéphane Chazelas

2
@Ankit คุณสามารถเริ่มต้นด้วย mywiki.wooledge.org/ParsingLs
Stéphane Chazelas

1
เมื่อคุณเข้าใจคำแนะนำของ @ StéphaneChazelasอย่างสมบูรณ์เกี่ยวprintfกับการใช้เพื่อสร้างรายการที่แต่ละชื่อถูกยกเลิกด้วยอักขระ null เพื่อให้สามารถประมวลผลได้โดยxargsใช้-0ตัวเลือกฉันขอแนะนำให้คุณแก้ไขคำตอบเพื่ออัปเดตด้วยรูปแบบของเขา ฉันค่อนข้างมั่นใจว่าเขายินดีที่คุณจะใช้ข้อมูลโค้ดของเขาหากคุณเข้าใจและเรียนรู้วิธีป้องกันพฤติกรรมที่ไม่พึงประสงค์ซึ่งเกิดจากชื่อไฟล์บางอย่างที่อาจมีอยู่
Anthony G - ความยุติธรรมสำหรับ Monica

1
การใช้xargsจะมีข้อได้เปรียบเหนือคำตอบที่ยอมรับได้ (ใช้งานได้เมื่อมีไฟล์ / ไดเรกทอรีจำนวนมากในไดเรกทอรีปัจจุบัน) ดังนั้นจึงมีขอบเขตสำหรับการแก้ไขในคำตอบที่เป็นประโยชน์ โดยส่วนตัวฉันพบว่าการตอบคำถามStack Exchangeเป็นประสบการณ์การเรียนรู้ที่ดีโดยเฉพาะเมื่อฉันได้รับข้อมูลย้อนกลับที่เป็นประโยชน์จากผู้ใช้รายอื่น
Anthony G - ความยุติธรรมสำหรับ Monica

-1

rm -rf <directory name>. มันได้ผล. เพียงแค่พิมพ์rm <directory name>จะนำไปสู่คำถามย่อยที่แต่ละไดเรกทอรีย่อยจะต้องลบออกด้วยตนเอง แต่rm -rfช่วยในการลบไดเรกทอรีทั้งหมดพร้อมกับไดเรกทอรีย่อยในครั้งเดียว


5
OP ขอให้เก็บเนื้อหาของไดเรกทอรีปัจจุบัน
สตีเฟ่น Rauch
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.