Jawaban:
Inilah solusi sederhana yang mungkin sebaiknya Anda gunakan:
mv filename.gif filename.gif.keep
rm *.gif
mv filename.gif.keep filename.gif
Tidak ada yang istimewa dengan .keep
ekstensi, ini hanya membuatnya agar nama file sementara tidak berakhir .gif
.
Jika Anda tidak boleh mengganti nama file (dan ada situasi skrip di mana ini penting):
for X in *.gif; do
if [ "$X" != "filename.gif" ]; then
rm "$X"
fi
done
Atau Anda dapat menulisnya lebih pendek seperti ini:
for X in *.gif; do [ "$X" != "filename.gif" ] && rm "$X"; done
Anda mungkin lebih suka menggunakan find
; itu sangat kuat, Anda mungkin menganggapnya lebih mudah dibaca, dan lebih baik menangani nama file aneh dengan karakter seperti *
di dalamnya .
find . -maxdepth 1 -not -name 'filename.gif' -name '*.gif' -delete
Saya telah menggunakan -not
operator untuk keterbacaan, tetapi jika kepatuhan POSIX penting - jika Anda tidak menggunakan GNU find, atau jika ini untuk skrip Anda bermaksud mendistribusikan ulang ke orang lain atau berjalan di berbagai sistem - Anda harus gunakan !
operator sebagai gantinya:
find . -maxdepth 1 ! -name 'filename.gif' -name '*.gif' -delete
Satu hal praktis tentang hal find
ini adalah Anda dapat dengan mudah memodifikasi perintah untuk case-insensitivity, sehingga ia menemukan dan menghapus file dengan ekstensi seperti .GIF
juga:
find . -maxdepth 1 -not -name 'filename.gif' -iname '*.gif' -delete
Harap dicatat bahwa saya telah digunakan -iname
di tempat -name
untuk pola pencarian *.gif
tapi saya tidak menggunakannya untuk filename.gif
. Agaknya Anda tahu persis apa nama file Anda, dan -iname
akan cocok dengan huruf kapital alternatif tidak hanya dalam ekstensi , tetapi di mana saja dalam nama file.
Semua solusi ini hanya menghapus file yang berada langsung di direktori saat ini . Mereka tidak menghapus file yang tidak ada dalam direktori saat ini, dan mereka tidak menghapus file yang berada di subdirektori dari direktori saat ini.
Jika Anda ingin menghapus file di mana saja yang terdapat dalam direktori saat ini (yaitu, termasuk dalam subdirektori, dan dalam subdirektori dari subdirektori tersebut, dan sebagainya - file yang terkandung dalam direktori saat ini atau salah satu turunannya), gunakan find
tanpa maxdepth -1
:
find . -not -name 'filename.gif' -name '*.gif' -delete
Hati-hati dengan ini!
Anda juga dapat mengatur nilai lain dengan -maxdepth
. Misalnya, untuk menghapus file di direktori saat ini dan anak-cucunya tetapi tidak lebih dalam:
find . -maxdepth 3 -not -name 'filename.gif' -name '*.gif' -delete
Pastikan Anda tidak pernah memprioritaskan -delete
, sebelum ekspresi lainnya! Anda akan melihat saya selalu menempatkan -delete
di akhir. Jika Anda meletakkannya di awal, itu akan dievaluasi terlebih dahulu, dan semua file di bawah .
(termasuk file yang tidak berakhir .gif
dan file dalam sub-sub-sub ... direktori dari .
) akan dihapus!
Untuk informasi lebih lanjut , lihat halaman manual untuk bash
dan sh
dan untuk perintah yang digunakan dalam contoh ini: mv
, rm
, [
, dan (terutama) find
.
find
, yang sangat fleksibel.
find
menangani nama file aneh dengan *
mereka lebih baik daripada for-loop? Untuk loop menangani file dengan *
baik, karena Anda telah menggunakan tanda kutip ganda.
Jika Anda menggunakan bash
(shell default), extglob
opsi shell memungkinkan Anda untuk menggunakan sintaks yang cocok dengan pola yang diperluas. Untuk mengaktifkannya, gunakan shopt
perintah builtin:
shopt -s extglob
(Saya menyertakan baris itu di .bashrc
file saya .)
Antara lain, itu memberikan akses ke !()
operator, yang cocok dengan pola apa pun yang tidak di dalam parens. Untuk tujuan Anda:
rm !(filename).gif
Informasi lebih lanjut tersedia di man bash
bawah "Pencocokan Pola".
extglob
harus diaktifkan, tetapi tidak ada hal buruk terjadi jika dinonaktifkan (dalam hal ini, ini tidak berfungsi). Dan tampaknya diaktifkan secara default, meskipun saya tidak memiliki shopt -s extglob
file konfigurasi (atau global) saya. Jika ada penjelasan sederhana mengapa itu berhasil bagi saya di luar kotak, Anda mungkin ingin menambahkannya ke jawaban ini; atau saya dapat memposting pertanyaan baru.
Buka Terminal dengan Ctrl+ Alt+ Tdan ketik:
find . -type f -name "*.gif" -and -not -name "filename.gif" -exec rm -vf {} \;
Perbedaan antara -delete
dan -exec rm -vf {} \;
adalah bahwa dengan opsi kedua, Anda akan dapat melihat file mana yang telah dihapus, karena -v
benderanya. Itu sesuatu yang tidak bisa dilakukan dengan -delete
opsi. ( -name -delete
akan mencetak nama file, tetapi rm
dengan -v
mengungkapkan jika setiap file berhasil dihapus.)
Ada GLOBIGNORE
variabelnya. Dari man bash
:
GLOBIGNORE
A colon-separated list of patterns defining the set of filenames
to be ignored by pathname expansion. If a filename matched by a
pathname expansion pattern also matches one of the patterns in
GLOBIGNORE, it is removed from the list of matches.
Jadi, cara sederhana adalah dengan hanya mengatur GLOBGINORE
nama file yang dimaksud:
$ touch {a,b,c,d}.png
$ echo *.png
a.png b.png c.png d.png
$ GLOBIGNORE=c.png
$ echo *.png
a.png b.png d.png
Jadi, dalam kasus Anda:
GLOBIGNORE=filename.gif; rm *.gif
Tentu saja, karena GLOBIGNORE
berisi pola, Anda dapat menggunakannya kapan pun Anda ingin mengecualikan pola:
$ GLOBIGNORE='[a-c].png'; echo *.png
d.png
$ touch bd.png; GLOBIGNORE='?.png'; echo *.png
bd.png
Keuntungan (?!) Dari GLOBIGNORE
pengaturan itu secara otomatis mengecualikan .
dan..
tidak cocok, dan memungkinkan dotglob
:
The GLOBIGNORE shell variable may be used to restrict the set of file‐
names matching a pattern. If GLOBIGNORE is set, each matching filename
that also matches one of the patterns in GLOBIGNORE is removed from the
list of matches. The filenames ``.'' and ``..'' are always ignored
when GLOBIGNORE is set and not null. However, setting GLOBIGNORE to a
non-null value has the effect of enabling the dotglob shell option, so
all other filenames beginning with a ``.'' will match. To get the old
behavior of ignoring filenames beginning with a ``.'', make ``.*'' one
of the patterns in GLOBIGNORE. The dotglob option is disabled when
GLOBIGNORE is unset.
Jadi, cara sederhana menghapus semua file dan folder dalam direktori:
GLOBIGNORE=.; rm -r *
The *
akan cocok nama file yang dimulai dengan .
, sejak GLOBIGNORE
diaktifkan dotglob
, tetapi tidak akan cocok .
atau ..
, sehingga Anda tidak akan mempengaruhi direktori induk seperti itu.