Jawaban:
cd <the directory you want>
find . -type f ! -iname "*.pdf" -delete
.pdf
nama fileMisalnya, jika ada direktori yang dipanggil temp
di folder rumah Anda:
cd ~/temp
lalu hapus file:
find . -type f ! -iname "*.pdf" -delete
Ini akan menghapus semua file kecuali xyz.pdf
.
Anda dapat menggabungkan dua perintah ini untuk:
find ~/temp -type f ! -iname "*.pdf" -delete
.
adalah direktori saat ini. !
berarti mengambil semua file kecuali yang ada .pdf
di akhir. -type f
hanya memilih file, bukan direktori. -delete
berarti menghapusnya.
!
harus datang sebelumnya -name
. hanya -name
akan mencakup saja .pdf
, sementara -iname
akan mencakup keduanya .pdf
dan.PDF
Untuk menghapus hanya di direktori saat ini dan tidak di sub-direktori tambahkan -maxdepth 1
:
find . -maxdepth 1 -type f ! -iname "*.pdf" -delete
.
berarti direktori saat ini. !
artinya mengambil semua file kecuali yang ada .pdf
di akhir. -delete
berarti menghapusnya. apakah saya jelas sekarang?
-maxdepth 1
parameter untuk memulai. Kemudian sarankan untuk menghapus parameter jika seseorang ingin menghapus secara rekursif.
Dengan bash
perpanjangan shell, Anda bisa menghapus file apa pun dengan ekstensi selain .pdf
menggunakan
rm -- *.!(pdf)
Sebagaimana dicatat oleh @pts, --
karakter menunjukkan akhir dari opsi perintah apa pun, membuat perintah aman dalam kasus yang jarang terjadi dari file yang namanya dimulai dengan -
karakter.
Jika Anda ingin menghapus file tanpa ekstensi apa pun serta ekstensi selain .pdf
, maka seperti yang ditunjukkan oleh @DennisWilliamson, Anda dapat menggunakan
rm -- !(*.pdf)
Perpanjangan globbing harus diaktifkan secara default, tetapi jika tidak Anda dapat melakukannya dengan menggunakan
shopt -s extglob
Terutama jika Anda berniat untuk menggunakan ini di dalam skrip, penting untuk dicatat bahwa jika ekspresi tidak cocok dengan apa pun (yaitu jika tidak ada file non-pdf dalam direktori), maka secara default glob akan diteruskan tidak diperluas ke rm
perintah, menghasilkan kesalahan seperti
rm: cannot remove `*.!(pdf)': No such file or directory
Anda dapat mengubah perilaku default ini menggunakan nullglob
opsi shell, namun itu memiliki masalah sendiri. Untuk diskusi yang lebih menyeluruh lihat NullGlob - Greg's Wiki
rm *~*.pdf
!(*.py)
. Juga, mungkin, jika OP hanya menginginkan file ".pdf" tersisa, maka file tanpa ekstensi juga harus dihapus dan tidak diabaikan.
$ cd <the directory you want>
$ gvfs-trash !(*.pdf)
Atau melalui mv
perintah (tetapi dengan cara ini Anda tidak dapat mengembalikannya dari Sampah karena tidak merekam informasi .trashinfo, jadi ini berarti Anda memindahkan file Anda ke tujuan di mana itu adalah sebagai berikut).
mv !(*.pdf) ~/.local/share/Trash/files
rm
.
Pendekatan termudah: Buat direktori lain di suatu tempat (jika Anda hanya menghapus dalam satu direktori, tidak secara rekursif, itu bahkan bisa menjadi subdirektori); pindahkan semua .pdf di sana; hapus yang lainnya; pindahkan kembali pdf; hapus direktori perantara.
Cepat, mudah, Anda dapat melihat apa yang Anda lakukan. Pastikan direktori perantara ada di perangkat yang sama dengan direktori yang Anda bersihkan sehingga gerakannya adalah penggantian nama, bukan salinan!
Gunakan bash's GLOBIGNORE:
GLOBIGNORE=x.pdf:a.pdf
rm *
unset GLOBIGNORE
Dari halaman manual bash:
GLOBIGNORE: Daftar pola yang dipisahkan titik dua yang mendefinisikan set nama file yang akan diabaikan oleh ekspansi pathname.
Tes cepat:
mkdir /tmp/foooooo
cd /tmp/foooooo
touch x.pdf y.zip z.mp3 a.pdf
GLOBIGNORE=x.pdf:a.pdf
ls -1 *
Keluaran:
y.zip z.mp3
Berikut ini pendekatan yang saya sukai, karena ini membuat saya sangat berhati-hati: menulis cara untuk menunjukkan file yang ingin saya hapus, kemudian mengirimkannya untuk rm
digunakan xargs
. Sebagai contoh:
ls
Tunjukkan semuanyals | grep pdf
menunjukkan kepada saya file yang ingin saya simpan. Hmm.ls | grep -v pdf
menunjukkan yang sebaliknya: semua kecuali yang ingin saya simpan. Dengan kata lain, ini menunjukkan daftar hal yang ingin saya hapus. Saya dapat mengkonfirmasi ini sebelum melakukan sesuatu yang berbahaya.ls | grep -v pdf | xargs rm
mengirimkan daftar itu ke rm
untuk dihapusSeperti yang saya katakan, saya terutama suka ini untuk keselamatan yang disediakannya: tidak disengaja rm *
bagi saya. Dua keuntungan lain:
ls
atau find
untuk mendapatkan daftar awal, seperti yang Anda inginkan. Anda dapat menggunakan apa pun yang Anda suka dalam proses mempersempit daftar itu - yang lain grep
, beberapa awk
, atau apa pun. Jika Anda hanya perlu menghapus file yang namanya mengandung warna, Anda dapat membuatnya dengan cara yang sama.find
untuk menemukan dan rm
untuk menghapus, daripada harus ingat yang find
menerima -delete
bendera. Dan jika Anda melakukan ini, sekali lagi, Anda dapat membuat solusi alternatif; mungkin alih-alih rm
, Anda bisa membuat trash
perintah yang memindahkan file ke tempat sampah (memungkinkan "undeletion") dan menyalurkannya ke sana rm
. Anda tidak perlu memiliki find
dukungan opsi itu, Anda hanya perlu melakukannya.Lihat komentar oleh @pabouk untuk bagaimana memodifikasi ini untuk menangani beberapa kasus tepi, seperti jeda baris dalam nama file, nama file seperti my_pdfs.zip
, dll.
pdf
namanya. --- b) Ini akan menghapus file PDF jika salah satu huruf dalam sufiks adalah huruf besar. --- c) Bukan ide yang baik untuk menggunakan output dari ls
. Itu tidak akan bekerja dengan nama file yang mengandung baris baru. Beberapa implementasi ls
ganti karakter khusus misalnya tab oleh ?
. --- Lebih baik untuk digunakan: find -maxdepth 1 -print0
. (tidak sesingkat ls
:) ----- Untuk menyelesaikan a) dan b) gunakan grep -vi '\.pdf$'
--- solusi lengkap (tapi hanya GNU):find -maxdepth 1 -print0 | grep -viz '\.pdf$' | xargs -0 rm
| head -20
setidaknya melihat apakah itu terlihat benar, sedangkan jika Anda hanya rm my_pattern
, Anda tidak memiliki kesempatan untuk menemukan kesalahan besar.
find . -type f ! -name "*.pdf"
untuk mencetak ke konsol, atau pipa ke file yang lebih sedikit atau. [dan kemudian pipa ke xargs ke rm jika diinginkan seperti komentar pabouk (dengan -print0 | ... -0 untuk nama file yang aneh)]
Saya biasanya memecahkan masalah seperti itu dari juru bahasa Python interaktif:
mic@mic ~ $ python
>>> import os
>>> for f in os.listdir('.'):
... if not f.endswith('.pdf'):
... os.remove(f)
Mungkin lebih lama dari satu-liner dengan find
atau xargs
, tapi itu sangat ulet, dan saya tahu persis apa yang dilakukannya, tanpa harus melakukan riset terlebih dahulu.
for item in [f for f in os.listdir('.') if not f.endswith('.pdf')]: os.remove(item)
python -c "import os; for f in os.listdir('.'): if not f.endswith('.pdf'): os.remove(f)"
[os.remove(f) for f in os.listdir('.') if not f.endswith('.pdf')]
jawaban yang lebih baik (dibandingkan dengan jawaban saya sebelumnya) untuk pertanyaan ini adalah dengan menggunakan file
perintah yang kuat .
$ file -i abc.pdf
abc: application/pdf; charset=binary
sekarang masalahmu:
cd <the directory you want to search in>
for var in ./*
do
if file -i "$var" | grep -q 'application/pdf\;'
then
echo "$var"
fi
done
tugas dari for
perintah adalah memberikan file dalam direktori saat ini dalam bentuk variabel $var
. if-then
perintah menampilkan nama-nama file pdf dengan mengambil status keluar 0
dari file -i "$var" | grep -q 'application/pdf\;'
perintah, itu akan memberikan status keluar 0
hanya jika menemukan file pdf.
rm $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}')
Peringatan! Lebih baik coba dulu
ls -l $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}')
-i
dengan grep
untuk pencocokan case-sensitive.
rm -i -- !(*@(a|x).pdf)
Baca sebagai, hapus semua file yang bukan a.pdf
atau x.pdf
.
Ini bekerja dengan memanfaatkan 2 gumpalan diperpanjang, bagian luar !()
untuk meniadakan gumpalan terkandung yang dengan sendirinya mengharuskan gumpalan harus cocok dengan satu atau lebih dari a
atau x
pola sebelum .pdf
sufiks. Lihat glob # extglob .
$ ls -a
.dotfile1 .dotfile2 a.pdf x.pdf y.zip z.mp3
$ echo -- !(a.pdf)
-- x.pdf y.zip z.mp3
$ echo -- !(x.pdf)
-- a.pdf y.zip z.mp3
$ echo -- !(a.pdf|x.pdf)
-- y.zip z.mp3
$ echo -- !(@(a|x).pdf) # NOTE.that this matches the .dotfiles* as well
-- . .. .dotfile1 .dotfile2 y.zip z.mp3
$ echo -- !(*@(a|x).pdf) # but this doesn't
-- y.zip z.mp3
$ echo rm -i -- !(*@(a|x).pdf)
rm -i -- y.zip z.mp3
$ ksh -c 'for i in ./*; do case $i in *.pdf)continue;; *)rm "$i";; esac;done'
Cukup banyak POSIX dan kompatibel dengan Bourne-gaya shell ( ksh
, bash
, dash
). Sangat cocok untuk skrip portabel dan ketika Anda tidak dapat menggunakan bash
globbing shell diperpanjang.
$ perl -le 'opendir(my $d,"."); foreach my $f (grep(-f && !/.pdf/ , readdir($d))){unlink $f};closedir $d'
Atau sedikit lebih bersih:
$ perl -le 'opendir(my $d,"."); map{ unlink $_ } grep(-f "./$_" && !/.pdf/ , readdir($d));closedir $d'
python -c 'import os;map(lambda x: os.remove(x), filter(lambda x: not x.endswith(".pdf"),os.listdir(".")))'
Berhati-hatilah dengan apa yang Anda hapus!
Cara aman untuk mengujinya sebelum mencoba menghapus adalah mengujinya terlebih dahulu ls
, karena beberapa perilaku yang tidak tertangkap dapat menghapus file yang tidak diinginkan. Dan Anda dapat melakukannya langsung di luar direktori. ls
mirip dengan rm
, jadi:
ls sub/path/to/files/!(*.pdf)
Ini akan mencantumkan
y.zip
z.mp3
Dan sekarang Anda dapat melihat apa yang Anda hapus dan dapat menghapusnya dengan aman:
rm sub/path/to/files/!(*.pdf)
Dan itu saja. Anda dapat menggunakan wildcard *
untuk menjadi lebih selektif seperti hanya menyimpan dokumen kursus pemrograman:
rm sub/path/to/files/!(*programming*)
.
berarti "dan"?!
berarti "kecuali"-name
menandakan bahwa Anda ingin mengecualikan dengan parameter nama dan kemudian-delete
adalah tindakan yang harus diambil setelah menemukan? Jadi mencari semuanya kecuali "* .pdf" dan menghapusnya? Atau apakah saya salah paham?