Kecualikan satu pola dari pertandingan glob

54

Saya memiliki beberapa file dengan nama file dasar yang sama. Saya ingin menghapus semua kecuali satu

foo.org #keep
foo.tex #delete
foo.fls #delete
foo.bib #delete
etc

Jika saya tidak perlu menyimpannya, saya tahu saya bisa menggunakannya rm foo.*.

TLDP menunjukkan ^untuk meniadakan pertandingan. Melalui trial and error, saya dapat menemukannya

rm foo.*[^org]

melakukan apa yang saya butuhkan, tetapi saya tidak begitu mengerti sintaksisnya.

Selain itu, meskipun bukan batasan dalam kasus penggunaan saya, saya pikir pola ini juga mengabaikan foo.odan foo.or. Bagaimana pola ini bekerja, dan seperti apa gumpalan yang mengabaikan hanya foo.org terlihat?

jake
sumber
1
Sebagai tambahan untuk jawaban @glen, perlu disebutkan bahwa rm foo.*[^org]menghapus semua file yang bukan karakter terakhiro , ratau g, jadi foo.footidak akan cocok dengan keduanya.
jimmij
Anda menggunakan a Regular Expression. Anda harus berhati-hati dengan karakter pengelompokan Anda. Dengan menggunakan tanda kurung Anda telah menentukan kelas karakter yang berarti bahwa Anda akan menghapus file yang memiliki ekstensi dengan huruf o, ratau gdalam urutan apa pun. Gunakan tanda kurung untuk membuat grup dan mempertahankan urutan karakter.
Tn. Mascaro
3
@ jbarker2160 - itu bukan benar-benar ekspresi reguler, itu lebih umum disebut glob (atau pola nama file ), yang lebih atau kurang merupakan himpunan bagian dari ekspresi reguler - lihat bagian pencocokan pola bash manpage untuk detailnya. Polanya foo.*[^org]akan cocok dengan nama file apa pun yang dimulai dengan foo.satu atau lebih karakter setelah titik di mana karakter terakhir bukan o, r, atau g. Sehingga akan cocok foo.orb, tapi tidak foo.orgatau foo.oratau foo.o. Jawaban GlennJackman menunjukkan cara mengaktifkan fitur pencocokan pola yang diperluas untuk meniadakan kecocokan.
Johnny

Jawaban:

52
shopt -s extglob
echo rm foo.!(org)

Ini "foo." diikuti oleh sesuatu BUKAN "org"

ref: https://www.gnu.org/software/bash/manual/bashref.html#Pattern-Matching

glenn jackman
sumber
Saya mencoba melakukan hal yang sama tetapi dengan tanda kurung dan ternyata ketika menggunakan tanda kurung itu tidak berfungsi
Donato
4
Apa sintaks yang cocok dengan beberapa nama file? katakanlah saya ingin mengecualikan .org, .png, .txt?
Freedo
@Freedo @()untuk daftar pola: stackoverflow.com/a/217208/3779853
phil294
23

Di bash, Anda juga bisa menggunakan GLOBIGNORE="*.org"; rm -i foo*.

Dan unset GLOBIGNOREsaat selesai.

Sebenarnya tidak lebih baik dari itu shopt -s extglob, tetapi saya merasa lebih mudah diingat.

mivk
sumber
5
@Ruslan Itu tidak berhasil. Anda harus melakukannya( GLOBIGNORE="*.org"; rm -i foo* )
DBedrenko
3
Catatan jika Anda ingin memperluas daftar yang diabaikan, pisahkan dengan titik dua, sepertiGLOBIGNORE="*foo*:*bar*"
phyatt
7

Sebuah pipa bisa lakukan?

ls * | grep -v "foo.org" | xargs -I {} echo {}

(jelas Anda mungkin ingin mengganti gema dengan rm di rantai terakhir).

Adobe
sumber
Berguna jika dibutuhkan hanya dalam satu baris.
bruceskyaus
1
Lebih mudah diingat (bagi saya, saya sering melakukan hal semacam itu) dan memungkinkan pemrosesan yang lebih kompleks untuk mem-boot :)
drevicko
1
ls -1harus lebih andal untuk memastikan semua file ditangani secara grepterpisah
MichaelChirico
0

OP sangat dekat:

rm foo.*[^o][^r][^g]

meskipun dalam hal *ini tidak perlu.

Tuan
sumber