Hapus semua kecuali satu (atau lebih) jenis tipe file

20

Saya sudah mencoba menemukan perintah untuk menghapus semua file dalam folder tetapi bukan jenis file. Tapi sepertinya saya tidak beruntung. Apa yang saya coba sejauh ini:

set extended_glob
rm !(*.dmg)
# this returns zsh:number expected

rm ./^*.dmg
# this returns no matches found 

Versi zsh yang saya gunakan adalah zsh 5.0.2 (x86_64-apple-darwin13.0.1).

Dzung Nguyen
sumber

Jawaban:

22

The extended_globpilihan memberikan zsh diperpanjang sendiri sintaks gumpal .

setopt extended_glob
rm -- ^*.dmg
rm -- ^*.(dmg|txt)

Anda dapat mengatur ksh_globopsi untuk mendapatkan gumpalan ksh . Berhati-hatilah bahwa dalam kasus umum di mana pola negatif adalah hal terakhir dalam kata, zsh dapat mengurai tanda kurung sebagai kualifikasi glob (tidak melakukannya dalam mode emulasi ksh).

setopt ksh_glob
rm -- !(*.dmg|*.txt)
setopt no_bare_glob_qual
rm -- !(*.dmg)
Gilles 'SANGAT berhenti menjadi jahat'
sumber
Ini sepertinya tidak berhasil. Ketika saya menjalankannya rm -r secrets/!(directory)terus meminta number expectedatau kadang-kadang itu memberi sayaevent not found: directory
CMCDragonkai
@CMCDragonkai "angka yang diharapkan" menunjukkan bahwa Anda tidak mengatur ksh_globopsi. "Event tidak ditemukan: direktori" menunjukkan bahwa Anda menjalankan bash (yang juga memahami !(…)sintaks, tetapi hanya setelah shopt -s extglob).
Gilles 'SANGAT berhenti menjadi jahat'
Bagaimana saya bisa menjalankan bash ketika saya berada di shell zsh saya?
CMCDragonkai
Bagi saya, setopt ksh_glob; echo !(a|b)bekerja sementara setopt ksh_glob; echo !(a)tidak ("nomor diharapkan") ...
ThiefMaster
@ThiefMaster saya punya masalah yang sama. Apakah ini bug?
CodeTower
5

Anda bisa menggunakan findbukan shell Anda:

find . -mindepth 1 -maxdepth 1 ! -name "*.dmg" -delete

Dari man find:

   ! expr True  if  expr  is false.  This character will also usually need
          protection from interpretation by the shell.
   -name pattern
          Base of file name (the path with the leading directories removed)
          matches shell pattern pattern. 
   -delete
          Delete  files; true if removal succeeded.  If the removal failed,
          an error message is issued.  If -delete fails, find's exit status
          will be nonzero (when  it eventually exits).  Use of -delete 
          automatically turns on the -depth option.

Jika Anda tidak dapat menggunakan finduntuk alasan apa pun, berikut adalah cara untuk melakukannya dengan zsh(atau cangkang lain). zshmenjadi zsh, mungkin ada cara sederhana untuk melakukan hal ini tapi karena aku bashpria, ini adalah apa yang saya datang dengan:

for file in *; do if [[ ! "$file" == *.dmg ]]; then rm $file; fi; done
terdon
sumber
Sayangnya, setiap kali saya menggunakan find di mac saya, itu hanya keluar dari sesi zsh saat ini tanpa pemberitahuan. Apakah Anda memiliki masalah yang sama ? find [Process completed]
Dzung Nguyen
1
@ nXqd lihat jawaban yang diperbarui untuk cara melakukannya tanpa find. Saya sarankan Anda memposting pertanyaan tentang findmasalah Anda , itu seharusnya tidak terjadi. Jika Anda melakukannya, sertakan output type -a find.
terdon
1
Bahkan dalam bash, ada solusi yang lebih sederhana:, rm !(*.dmg)setelah shopt -s extglob.
Gilles 'SANGAT berhenti menjadi jahat'
@terdon terima kasih atas kiat debug Anda di shell. outputnya tampaknya benar:find is a shell function find is /usr/bin/find
Dzung Nguyen
@nXqd itu tidak benar, seharusnya tidak menjadi fungsi shell, seharusnya hanya /usr/bin/find. Anda memiliki fungsi yang disebut finddidefinisikan di salah satu file konfigurasi bash Anda. Karena Anda menggunakan OSX, itu mungkin ~/.profile.
terdon
3

Cara lain untuk menghapus file adalah dengan find, xargsdan rm:

find . -mindepth 1 -maxdepth 1 ! -name '*.dmg' -print0 | xargs -0 rm
Dragos Rizescu
sumber