จะลบไฟล์หลายไฟล์พร้อมกันใน Bash บน Linux ได้อย่างไร


103

ฉันมีรายการไฟล์นี้บนเซิร์ฟเวอร์ Linux:

abc.log.2012-03-14
abc.log.2012-03-27
abc.log.2012-03-28
abc.log.2012-03-29
abc.log.2012-03-30
abc.log.2012-04-02
abc.log.2012-04-04
abc.log.2012-04-05
abc.log.2012-04-09
abc.log.2012-04-10

ฉันได้ลบไฟล์บันทึกที่เลือกทีละไฟล์โดยใช้คำสั่งrm -rfดูด้านล่าง:

rm -rf abc.log.2012-03-14
rm -rf abc.log.2012-03-27
rm -rf abc.log.2012-03-28

มีวิธีอื่นเพื่อให้ฉันสามารถลบไฟล์ที่เลือกพร้อมกันได้หรือไม่?


4
และ "พูดว่า GNU / Linux ไม่ใช่แค่ Linux" ฉันได้ยินเสียงฟ้าร้องจากเบาะหลัง
Boris Stitnicky

8
ยังไงก็ตามทำไมถึง -rf? โฟลเดอร์เหล่านี้หรือไม่ f คือการบังคับ r คือการเรียกซ้ำ จะใช้งานได้หากเป็นเพียงไฟล์ แต่ได้รับการเตือนการใช้ -rf ทุกครั้งที่คุณต้องการลบบางสิ่งนั้นอันตรายมาก (มาก) (มาก) (และคุณควรเพิ่มแท็ก "bash" เนื่องจาก "linux" กว้างเกินไป
Depado

@BorisStitnicky - ฉันอยากรู้ว่าทำไมถึงGNUจำเป็น?
user66001

2
@ user66001: สำหรับความเห็นโครงการ GNU เกี่ยวกับเรื่องนี้: gnu.org/gnu/linux-and-gnu.html ฉันไม่มีจุดยืนในเรื่องนี้อย่างน้อยก็ไม่ได้อยู่ที่นี่และนี่ไม่ใช่สถานที่ที่จะถกเถียงกัน
Keith Thompson

2
@BorisStitnicky - ไม่จำเป็นต้องอภิปรายไม่ต้องสงสัยเลยและลิงค์นั้นให้ข้อมูลระดับที่ฉันกำลังมองหา +1
user66001

คำตอบ:


159

Bash รองรับไวลด์การ์ดและการขยายทุกประเภท

กรณีที่แน่นอนของคุณจะได้รับการจัดการโดยการขยายวงเล็บปีกกาดังนี้:

$ rm -rf abc.log.2012-03-{14,27,28}

ข้างต้นจะขยายเป็นคำสั่งเดียวที่มีทั้งสามอาร์กิวเมนต์และเทียบเท่ากับการพิมพ์:

$ rm -rf abc.log.2012-03-14 abc.log.2012-03-27 abc.log.2012-03-28

สิ่งสำคัญคือต้องสังเกตว่าส่วนขยายนี้ทำโดยเชลล์ก่อนที่rmจะโหลดด้วยซ้ำ


อย่าใช้ "rm" หากคุณต้องการกู้คืนไฟล์ในอนาคตคุณสามารถใช้ยูทิลิตี้ "rm-trash": github.com/nateshmbhat/rm-trash
Natesh bhat

75

ใช้สัญลักษณ์แทน ( *) เพื่อจับคู่ไฟล์หลายไฟล์

abc.log.2012-03-ตัวอย่างเช่นคำสั่งด้านล่างจะลบไฟล์ทั้งหมดที่มีชื่อขึ้นต้นด้วย

rm -f abc.log.2012-03-*

ฉันขอแนะนำให้เรียกใช้ls abc.log.2012-03-*เพื่อแสดงรายการไฟล์เพื่อให้คุณเห็นสิ่งที่คุณกำลังจะลบก่อนที่จะเรียกใช้rmคำสั่ง

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


มีประโยชน์มาก แต่ไม่ขอยืนยันการลบ โปรดทราบ.
nuriselcuk

1
@nuriselcuk คุณสามารถเพิ่ม -i เพื่อรับการยืนยันสำหรับแต่ละไฟล์ที่ถูกลบ
Felipe Romero

ทำงานได้อย่างมีเสน่ห์บน AWS Ec2-Instance ที่ใช้ Amazon Linux 1 :) ขอบคุณ
Kyle Bridenstine

41

หากคุณต้องการลบไฟล์ทั้งหมดที่มีชื่อตรงกับรูปแบบใดรูปแบบหนึ่งสัญลักษณ์แทน (รูปแบบลูกโลก) เป็นวิธีแก้ปัญหาที่ตรงไปตรงมาที่สุด ตัวอย่างบางส่วน:

$ rm -f abc.log.*             # Remove them all
$ rm -f abc.log.2012*         # Remove all logs from 2012
$ rm -f abc.log.2012-0[123]*  # Remove all files from the first quarter of 2012

นิพจน์ทั่วไปมีพลังมากกว่าสัญลักษณ์แทน คุณสามารถให้อาหารส่งออกของไปgrep rm -fตัวอย่างเช่นหากชื่อไฟล์บางชื่อขึ้นต้นด้วย"abc.log"และบาง"ABC.log"ชื่อgrepให้คุณทำการจับคู่แบบไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่:

$ rm -f $(ls | grep -i '^abc\.log\.')

ซึ่งจะทำให้เกิดปัญหาหากชื่อไฟล์ใด ๆ มีอักขระตลกรวมถึงช่องว่าง ระวัง.

เมื่อฉันทำสิ่งนี้ฉันจะรันls | grep ...คำสั่งก่อนและตรวจสอบว่ามันสร้างผลลัพธ์ที่ฉันต้องการ - โดยเฉพาะอย่างยิ่งถ้าฉันใช้rm -f:

$ ls | grep -i '^abc\.log\.'
(check that the list is correct)
$ rm -f $(!!)

โดยที่!!ขยายไปยังคำสั่งก่อนหน้า หรือฉันสามารถพิมพ์ลูกศรขึ้นหรือ Ctrl-P และแก้ไขบรรทัดก่อนหน้าเพื่อเพิ่มrm -fคำสั่ง

นี่ถือว่าคุณกำลังใช้ bash shell เชลล์อื่น ๆ โดยเฉพาะ csh และ tcsh และเชลล์ที่ได้รับ sh รุ่นเก่าบางตัวอาจไม่รองรับ$(...)ไวยากรณ์ คุณสามารถใช้ไวยากรณ์ backtick ที่เทียบเท่าได้:

$ rm -f `ls | grep -i '^abc\.log\.'`

$(...)ไวยากรณ์ง่ายต่อการอ่านและถ้าคุณมีความทะเยอทะยานจริงๆมันสามารถซ้อนกัน

สุดท้ายหากไฟล์ย่อยที่คุณต้องการลบไม่สามารถแสดงออกด้วยนิพจน์ทั่วไปได้อย่างง่ายดายเคล็ดลับที่ฉันมักใช้คือการแสดงรายการไฟล์ลงในไฟล์ข้อความชั่วคราวจากนั้นแก้ไข:

$ ls > list
$ vi list   # Use your favorite text editor

จากนั้นฉันสามารถแก้ไขlistไฟล์ด้วยตนเองเหลือเพียงไฟล์ที่ฉันต้องการลบจากนั้น:

$ rm -f $(<list)

หรือ

$ rm -f `cat list`

(อีกครั้งถือว่าไม่มีชื่อไฟล์ใดที่มีอักขระตลกโดยเฉพาะช่องว่าง)

หรือเมื่อแก้ไขlistไฟล์ฉันสามารถเพิ่มrm -f ที่จุดเริ่มต้นของแต่ละบรรทัดจากนั้น:

$ . ./list

หรือ

$ source ./list

แก้ไขไฟล์ยังเป็นโอกาสที่จะเพิ่มคำพูดที่จำเป็นเช่นการเปลี่ยนไปrm -f foo barrm -f 'foo bar'


8

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

[$]> rm abc.log.2012-03-14 abc.log.2012-03-27 abc.log.2012-03-28 abc.log.2012-03-29 abc.log.2012-03-30 abc.log.2012-04-02 abc.log.2012-04-04 abc.log.2012-04-05 abc.log.2012-04-09 abc.log.2012-04-10

นี่ควรเป็นคำตอบที่ได้รับการยอมรับเนื่องจากตอบคำถามที่วางไว้อย่างชัดเจน เป็นมิตรกับผู้คนที่มาที่นี่จาก Google มากขึ้น
ATLief

5

ไวลด์การ์ดจะใช้งานได้ดีสำหรับสิ่งนี้แม้ว่าจะปลอดภัย แต่ก็เป็นการดีที่สุดที่จะใช้ไวด์การ์ดให้น้อยที่สุดเท่าที่จะเป็นไปได้ดังนั้นสิ่งที่อยู่ในแนวนี้:

rm -rf abc.log.2012-*

แม้ว่าจากรูปลักษณ์ของมันเป็นเพียงไฟล์เดียวหรือไม่? ไม่จำเป็นต้องใช้ตัวเลือกการเรียกซ้ำหากไม่มีรายการเหล่านั้นเป็นไดเร็กทอรีดังนั้นอย่าใช้สิ่งนั้นเพียงเพื่อความปลอดภัย


2

ฉันไม่ได้เป็นกูรูลินุกซ์ xargs rm -rfแต่ผมเชื่อว่าคุณต้องการที่จะท่อรายชื่อของไฟล์ที่ส่งออกไป ฉันเคยใช้อะไรแบบนี้ในอดีตได้ผลดี ทดสอบกับไดเร็กทอรีตัวอย่างก่อน!

แก้ไข - ฉันอาจเข้าใจผิดจากคำตอบอื่น ๆ ที่ปรากฏ หากคุณสามารถใช้สัญลักษณ์แทนได้ก็เยี่ยมมาก ฉันคิดว่ารายการเดิมของคุณที่คุณแสดงนั้นสร้างขึ้นโดยโปรแกรมเพื่อให้คุณ "เลือก" ดังนั้นฉันคิดว่าการวางท่อxargsจะเป็นหนทางที่จะไป


-1

หากคุณต้องการลบไฟล์ทั้งหมดที่อยู่ในไดเร็กทอรีพร้อมกัน ตัวอย่างเช่นชื่อไดเรกทอรีของคุณคือ "log" และ "log" ได้แก่ ไฟล์ abc.log.2012-03-14, abc.log.2012-03-15, ... ฯลฯ คุณต้องอยู่เหนือไดเร็กทอรีบันทึกและ:

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