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 .keep
nell'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 find
invece; è 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' -not
operatore 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 -iname
al posto del -name
per il modello di ricerca *.gif
ma non ho , non utilizzato per filename.gif
. Presumibilmente sai esattamente come si chiama il tuo file e -iname
corrisponderà 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 -delete
primo, prima delle altre espressioni! Vedrai che l'ho sempre messo -delete
alla fine. Se lo metti all'inizio, verrebbe valutato per primo, e tutti i file in .
(compresi i file che non finiscono .gif
e i file nelle directory sub-sub ... sub .
) vengono eliminati!
Per ulteriori informazioni , consultare le pagine di manuale per bash
e sh
e per i comandi utilizzati in questi esempi: mv
, rm
, [
, e (soprattutto) find
.
find
, che è altamente versatile.
find
gestisce 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' extglob
opzione shell consente di utilizzare una sintassi di corrispondenza del modello estesa. Per abilitarlo, utilizzare il shopt
comando incorporato:
shopt -s extglob
(Includo quella riga nel mio .bashrc
file.)
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".
extglob
deve 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 extglob
in 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 -delete
e -exec rm -vf {} \;
è che con la seconda opzione, sarai in grado di vedere quali file sono stati rimossi, a causa del -v
flag. È qualcosa che non si può fare con l' -delete
opzione. ( -name -delete
stamperà i nomi dei file, ma rm
con -v
rivela se ogni file era stato eliminato con successo .)
C'è la GLOBIGNORE
variabile 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é GLOBIGNORE
contiene 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 GLOBIGNORE
abilitata dotglob
, ma non corrisponderà .
o ..
, in modo da non influenzare la directory padre in quel modo.