Escludere un modello dalla corrispondenza glob


54

Ho diversi file con lo stesso nome file di base. Vorrei rimuovere tutti tranne uno

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

Se non avessi bisogno di tenerne uno, so che potrei usarlo rm foo.*.

TLDP dimostra ^di annullare una corrispondenza. Attraverso tentativi ed errori, sono stato in grado di trovarlo

rm foo.*[^org]

fa quello che mi serve, ma non capisco davvero la sintassi.

Inoltre, sebbene non sia una limitazione nel mio caso d'uso, penso che questo modello ignori anche foo.oe foo.or. Come funziona questo modello, e quale sarebbe un glob che ignora solo foo.org assomigliare?


1
Come aggiunta alla risposta di @glen, vale la pena ricordare che rm foo.*[^org]rimuove tutti i file che l' ultimo carattere non è né o, rg, quindi foo.foo, non corrisponderebbe neanche.
Jimmij,

Stai utilizzando un Regular Expression. Dovresti stare attento con i tuoi personaggi di raggruppamento. Usando le parentesi hai specificato una classe di caratteri che significa che elimineresti qualsiasi file che avesse un'estensione con le lettere o, ro gin qualsiasi ordine. Utilizzare le parentesi per creare un gruppo e preservare l'ordine dei caratteri.
Mr. Mascaro,

3
@ jbarker2160 - questa non è in realtà un'espressione regolare, è più comunemente chiamata glob (o pattern di nome file ), che è più o meno un sottoinsieme di un'espressione regolare - vedi la sezione di corrispondenza dei pattern nella pagina man di bash per i dettagli. Il suo modello foo.*[^org]corrisponderà a qualsiasi nome di file che inizia con foo.uno o più caratteri dopo il punto in cui l'ultimo carattere non è o, r o g. Quindi corrisponderebbe foo.orb, ma non foo.orgo foo.oro foo.o. La risposta di GlennJackman mostra come abilitare le funzionalità di corrispondenza estesa del modello per annullare una corrispondenza.
Johnny,

Risposte:


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

Questo è "pippo". seguito da qualsiasi cosa NON "org"

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


Ho provato a fare lo stesso ma con le parentesi e apparentemente quando si usano le parentesi non funziona
Donato

4
Qual è la sintassi per abbinare più nomi di file? dire che voglio escludere .org, .png, .txt?
Freedo il

@Freedo @()per un modello-list: stackoverflow.com/a/217208/3779853
phil294

23

In bash, puoi anche usare GLOBIGNORE="*.org"; rm -i foo*.

E unset GLOBIGNOREquando fatto.

Non è molto meglio di shopt -s extglob, ma trovo più facile da ricordare.


5
@Ruslan Non funziona. Dovresti fare( GLOBIGNORE="*.org"; rm -i foo* )
DBedrenko il

3
Nota se si desidera espandere l'elenco di ignorati, separarli con due punti, comeGLOBIGNORE="*foo*:*bar*"
phyatt

7

Una pipa può fare?

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

(ovviamente potresti voler sostituire echo con rm nell'ultima catena).


Utile se necessario in una sola riga.
Bruceskyaus

1
Più facile da ricordare (per me, faccio spesso quel genere di cose) e consente l'avvio di elaborazioni più complesse :)
drevicko

1
ls -1dovrebbe essere più affidabile per garantire che tutti i file vengano gestiti grepseparatamente
MichaelChirico,

-1

OP era molto vicino:

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

sebbene in questo caso *non sia necessario.


questo non verrà rimosso foo.ortefoo.erg
Adam Katz il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.