Bagaimana cara menghapus banyak file sekaligus di Bash di Linux?

103

Saya memiliki daftar file ini di server 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

Saya telah menghapus file log yang dipilih satu per satu, menggunakan perintah rm -rflihat di bawah ini:

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

Apakah ada cara lain agar saya dapat menghapus file yang dipilih sekaligus?

pengguna1253847
sumber
4
Dan "Katakan GNU / Linux, bukan hanya Linux", saya mendengar seseorang bergemuruh dari kursi belakang.
Boris Stitnicky
8
Ngomong-ngomong, kenapa tthe -rf? Apakah folder-folder ini? f untuk memaksa, r untuk rekursif. Ini akan berfungsi jika hanya sebuah file tetapi diperingatkan, menggunakan -rf setiap kali Anda ingin menghapus sesuatu sangat (sangat) (sangat sangat) berbahaya. (dan Anda harus menambahkan tag "bash" karena "linux" terlalu lebar.
Depado
@BorisStitnicky - Saya penasaran mengapa GNUini diperlukan?
pengguna66001
2
@ user66001: Untuk opini proyek GNU tentang masalah ini: gnu.org/gnu/linux-and-gnu.html . Saya tidak mengambil posisi tentang masalah ini, setidaknya tidak di sini, dan ini bukan tempat untuk memperdebatkannya.
Keith Thompson
2
@BorisStitnicky - Tidak perlu berdebat, sama sekali tidak mengerti, dan tautan itu memberi saya tingkat informasi yang saya cari +1
pengguna66001

Jawaban:

159

Bash mendukung semua jenis wildcard dan ekspansi.

Kasus persis Anda akan ditangani oleh ekspansi brace , seperti:

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

Di atas akan berkembang menjadi satu perintah dengan ketiga argumen, dan setara dengan mengetik:

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

Penting untuk dicatat bahwa ekspansi ini dilakukan oleh shell, rmbahkan sebelum dimuat.

beristirahat
sumber
Jangan gunakan "rm" jika Anda ingin memulihkan file di masa mendatang. Anda dapat menggunakan utilitas "rm-trash": github.com/nateshmbhat/rm-trash
Natesh bhat
75

Gunakan karakter pengganti ( *) untuk mencocokkan beberapa file.

Misalnya, perintah di bawah ini akan menghapus semua file dengan nama yang diawali dengan abc.log.2012-03-.

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

Saya akan merekomendasikan ls abc.log.2012-03-*untuk menjalankan daftar file sehingga Anda dapat melihat apa yang akan Anda hapus sebelum menjalankan rmperintah.

Untuk lebih jelasnya lihat halaman manual Bash pada perluasan nama file .

dogbane
sumber
Sangat berguna, tetapi tidak meminta konfirmasi untuk menghapus. Mohon berhati-hati.
nuriselcuk
1
@nuriselcuk Anda dapat menambahkan -i untuk mendapatkan konfirmasi untuk setiap file yang dihapus.
Felipe Romero
Bekerja dengan sangat baik di AWS Ec2-Instance yang menjalankan Amazon Linux 1 :) Terima kasih.
Kyle Bridenstine
41

Jika Anda ingin menghapus semua file yang namanya cocok dengan formulir tertentu, wildcard (pola glob) adalah solusi yang paling mudah. Beberapa contoh:

$ 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

Ekspresi reguler lebih efektif daripada karakter pengganti; Anda dapat memberi makan keluaran grepke rm -f. Misalnya, jika beberapa nama file diawali dengan "abc.log"dan beberapa dengan "ABC.log", grepmemungkinkan Anda melakukan pencocokan tidak peka huruf besar / kecil:

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

Ini akan menimbulkan masalah jika salah satu nama file mengandung karakter lucu, termasuk spasi. Hati-hati.

Ketika saya melakukan ini, saya menjalankan ls | grep ...perintah terlebih dahulu dan memeriksa apakah itu menghasilkan output yang saya inginkan - terutama jika saya menggunakan rm -f:

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

di mana !!meluas ke perintah sebelumnya. Atau saya bisa mengetik panah atas atau Ctrl-P dan mengedit baris sebelumnya untuk menambahkan rm -fperintah.

Ini mengasumsikan Anda menggunakan bash shell. Beberapa shell lain, terutama csh dan tcsh dan beberapa shell turunan sh yang lebih lama, mungkin tidak mendukung $(...)sintaks. Anda dapat menggunakan sintaks backtick yang setara:

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

The $(...)sintaks lebih mudah dibaca, dan jika Anda benar-benar ambisius itu bisa bersarang.

Terakhir, jika subset file yang ingin Anda hapus tidak dapat dengan mudah diekspresikan dengan ekspresi reguler, trik yang sering saya gunakan adalah mencantumkan file ke file teks sementara, lalu mengeditnya:

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

Saya kemudian dapat mengedit listfile secara manual, hanya menyisakan file yang ingin saya hapus, dan kemudian:

$ rm -f $(<list)

atau

$ rm -f `cat list`

(Sekali lagi, ini mengasumsikan tidak ada nama file yang mengandung karakter lucu, terutama spasi.)

Atau, saat mengedit listfile, saya dapat menambahkan rm -f ke awal setiap baris dan kemudian:

$ . ./list

atau

$ source ./list

Mengedit file juga merupakan kesempatan untuk menambahkan tanda kutip jika perlu, misalnya mengubah rm -f foo barmenjadi rm -f 'foo bar'.

Keith Thompson
sumber
8

Cukup gunakan pilihan multiline di sublime untuk menggabungkan semua file menjadi satu baris dan tambahkan spasi di antara setiap nama file lalu tambahkan rmdi awal daftar. Ini sebagian besar berguna ketika tidak ada pola dalam nama file yang ingin Anda hapus.

[$]> 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
Andy
sumber
Ini harus menjadi jawaban yang diterima karena secara eksplisit menjawab pertanyaan yang diajukan. Lebih ramah kepada orang yang datang ke sini dari Google.
ATLief
5

Kartu liar akan bekerja dengan baik untuk ini, meskipun untuk amannya akan lebih baik untuk menggunakan kartu liar seminimal mungkin, jadi sesuatu di sepanjang baris ini:

rm -rf abc.log.2012-*

Meskipun dari kelihatannya, apakah itu hanya file tunggal? Opsi rekursif tidak diperlukan jika tidak ada item yang merupakan direktori, jadi sebaiknya jangan gunakan itu, hanya untuk keamanan.

lacrosse1991
sumber
2

Saya bukan ahli linux, tapi saya yakin Anda ingin menyalurkan daftar file keluaran ke xargs rm -rf. Saya telah menggunakan sesuatu seperti ini di masa lalu dengan hasil yang bagus. Uji pada direktori sampel terlebih dahulu!

EDIT - Saya mungkin salah paham, berdasarkan jawaban lain yang muncul. Jika Anda bisa menggunakan wildcard, bagus. Saya berasumsi bahwa daftar asli Anda yang Anda tampilkan dihasilkan oleh program untuk memberi Anda "pilihan", jadi saya pikir piping to xargsadalah cara yang tepat.

Dave
sumber
-1

jika Anda ingin menghapus semua file yang termasuk dalam direktori sekaligus. Misalnya: nama Direktori Anda adalah "log" dan direktori "log" termasuk file abc.log.2012-03-14, abc.log.2012-03-15, ... dll. Anda harus berada di atas direktori log dan:

rm -rf /log/*
Alican
sumber