Risposte:
Ecco la semplice soluzione che probabilmente dovresti usare:
mv filename.gif filename.gif.keep
rm *.gif
mv filename.gif.keep filename.gif
Non c'è niente di speciale .keepnell'estensione, questo lo rende solo in modo che il nome file non finisca temporaneamente .gif.
Se non è necessario rinominare il file (e ci sono situazioni di scripting in cui questo è importante):
for X in *.gif; do
if [ "$X" != "filename.gif" ]; then
rm "$X"
fi
done
Oppure puoi scriverlo più breve in questo modo:
for X in *.gif; do [ "$X" != "filename.gif" ] && rm "$X"; done
È preferibile utilizzare findinvece; è molto potente, potresti considerarlo più leggibile e gestisce meglio nomi di file strani con personaggi come *in essi .
find . -maxdepth 1 -not -name 'filename.gif' -name '*.gif' -delete
Ho usato l' -notoperatore per la leggibilità, ma se la conformità POSIX è importante - se non stai usando GNU find, o se questo è per uno script che intendi ridistribuire ad altri o eseguire su una varietà di sistemi - dovresti usa !invece l' operatore:
find . -maxdepth 1 ! -name 'filename.gif' -name '*.gif' -delete
Una cosa utile findè che puoi facilmente modificare il comando per la distinzione tra maiuscole e minuscole, in modo da trovare ed eliminare i file con estensioni come .GIF:
find . -maxdepth 1 -not -name 'filename.gif' -iname '*.gif' -delete
Si prega di notare che ho usato -inameal posto del -nameper il modello di ricerca *.gifma non ho , non utilizzato per filename.gif. Presumibilmente sai esattamente come si chiama il tuo file e -inamecorrisponderà a maiuscole / minuscole alternative non solo nell'estensione , ma ovunque nel nome del file.
Tutte queste soluzioni eliminano solo i file che risiedono immediatamente nella directory corrente . Non eliminano i file non contenuti nella directory corrente e non eliminano i file che risiedono nelle sottodirectory della directory corrente.
Se si desidera eliminare i file ovunque contenuti all'interno della directory corrente (ovvero, anche nelle sottodirectory e nelle sottodirectory di tali sottodirectory, e così via - file contenuti nella directory corrente o in uno dei suoi discendenti), utilizzare find senza maxdepth -1 :
find . -not -name 'filename.gif' -name '*.gif' -delete
Stai attento con questo!
Puoi anche impostare altri valori con -maxdepth. Ad esempio, per eliminare i file nella directory corrente e i suoi figli e nipoti, ma non più in profondità:
find . -maxdepth 3 -not -name 'filename.gif' -name '*.gif' -delete
Assicurati solo di non mettere mai il -deleteprimo, prima delle altre espressioni! Vedrai che l'ho sempre messo -deletealla fine. Se lo metti all'inizio, verrebbe valutato per primo, e tutti i file in .(compresi i file che non finiscono .gife i file nelle directory sub-sub ... sub .) vengono eliminati!
Per ulteriori informazioni , consultare le pagine di manuale per bashe she per i comandi utilizzati in questi esempi: mv, rm, [, e (soprattutto) find.
find, che è altamente versatile.
findgestisce i nomi di file strani con *in loro meglio del for-loop? Il ciclo for gestisce *bene i file , perché hai usato virgolette doppie.
Se si utilizza bash(la shell predefinita), l' extglobopzione shell consente di utilizzare una sintassi di corrispondenza del modello estesa. Per abilitarlo, utilizzare il shoptcomando incorporato:
shopt -s extglob
(Includo quella riga nel mio .bashrcfile.)
Tra le altre cose, consente l'accesso !()all'operatore, che corrisponde a qualsiasi modello non all'interno delle parentesi. Per il tuo scopo:
rm !(filename).gif
Maggiori informazioni sono disponibili in man bash"Pattern Matching".
extglobdeve essere abilitata, ma non succede nulla di male se è disabilitato (in quel caso, semplicemente non funziona). E sembra essere abilitato per impostazione predefinita, anche se non ho shopt -s extglobin nessuno dei miei file di configurazione (o globale). Se c'è una semplice spiegazione del motivo per cui funziona per me fuori dalla scatola, potresti volerlo aggiungere a questa risposta; o potrei pubblicare una nuova domanda.
Apri un terminale con Ctrl+ Alt+ Te digita:
find . -type f -name "*.gif" -and -not -name "filename.gif" -exec rm -vf {} \;
La differenza tra -deletee -exec rm -vf {} \;è che con la seconda opzione, sarai in grado di vedere quali file sono stati rimossi, a causa del -vflag. È qualcosa che non si può fare con l' -deleteopzione. ( -name -deletestamperà i nomi dei file, ma rmcon -vrivela se ogni file era stato eliminato con successo .)
C'è la GLOBIGNOREvariabile A partire dalman 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.
Quindi, un modo semplice è semplicemente impostare GLOBGINORE il nome del file in questione:
$ 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
Quindi, nel tuo caso:
GLOBIGNORE=filename.gif; rm *.gif
Naturalmente, poiché GLOBIGNOREcontiene motivi, è possibile utilizzarlo ogni volta che si desidera escludere un motivo:
$ GLOBIGNORE='[a-c].png'; echo *.png
d.png
$ touch bd.png; GLOBIGNORE='?.png'; echo *.png
bd.png
Un vantaggio (?!) Di GLOBIGNOREè l'impostazione che esclude automaticamente .e.. dalla corrispondenza, e consente di 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.
Quindi, un modo semplice per eliminare tutti i file e le cartelle in una directory:
GLOBIGNORE=.; rm -r *
Il *corrisponderà nomi di file che iniziano con ., in quanto GLOBIGNOREabilitata dotglob, ma non corrisponderà .o .., in modo da non influenzare la directory padre in quel modo.