Respuestas:
Aquí está la solución simple que probablemente debería usar:
mv filename.gif filename.gif.keep
rm *.gif
mv filename.gif.keep filename.gif
La .keep
extensión no tiene nada de especial , esto solo hace que el nombre de archivo no termine temporalmente .gif
.
Si no debe cambiar el nombre del archivo (y hay situaciones de secuencias de comandos donde esto es importante):
for X in *.gif; do
if [ "$X" != "filename.gif" ]; then
rm "$X"
fi
done
O puedes escribirlo más corto así:
for X in *.gif; do [ "$X" != "filename.gif" ] && rm "$X"; done
Puede preferir usar find
en su lugar; es muy poderoso, podría considerarlo más legible, y maneja mejor los nombres de archivos extraños con caracteres como *
en ellos .
find . -maxdepth 1 -not -name 'filename.gif' -name '*.gif' -delete
He utilizado el -not
operador para facilitar la lectura, pero si el cumplimiento de POSIX es importante, si no está utilizando GNU find, o si se trata de un script que tiene la intención de redistribuir a otros o ejecutar en una variedad de sistemas, debería use el !
operador en su lugar:
find . -maxdepth 1 ! -name 'filename.gif' -name '*.gif' -delete
Una cosa útil find
es que puede modificar fácilmente el comando para que no se distinga entre mayúsculas y minúsculas, para que también encuentre y elimine archivos con extensiones como .GIF
:
find . -maxdepth 1 -not -name 'filename.gif' -iname '*.gif' -delete
Tenga en cuenta que he utilizado -iname
en lugar de -name
para el patrón de búsqueda *.gif
, pero he no utilizado para filename.gif
. Presumiblemente, usted sabe exactamente cómo se llama su archivo y -iname
coincidirá con mayúsculas alternativas no solo en la extensión , sino en cualquier parte del nombre del archivo.
Todas estas soluciones solo eliminan archivos que residen inmediatamente en el directorio actual . No eliminan archivos no contenidos en el directorio actual, y no eliminan archivos que residen en subdirectorios del directorio actual.
Si desea eliminar archivos en todas partes contenidos en el directorio actual (es decir, incluidos en subdirectorios, y en subdirectorios de esos subdirectorios, etc. - archivos contenidos en el directorio actual o cualquiera de sus descendientes), use find
sin maxdepth -1
:
find . -not -name 'filename.gif' -name '*.gif' -delete
¡Ten cuidado con esto!
También puede establecer otros valores con -maxdepth
. Por ejemplo, para eliminar archivos en el directorio actual y sus hijos y nietos pero no más profundo:
find . -maxdepth 3 -not -name 'filename.gif' -name '*.gif' -delete
¡Solo asegúrate de nunca poner -delete
primero, antes de las otras expresiones! Verás que siempre pongo -delete
al final. Si lo pones al principio, se evaluaría primero, y todos los archivos debajo .
(incluidos los archivos que no terminan en .gif
y los archivos en los directorios sub-sub-sub-sub profundos ... .
) se eliminarán.
Para obtener más información , ver las páginas del manual para bash
y sh
y para los comandos utilizados en estos ejemplos: mv
, rm
, [
, y (especialmente) find
.
find
, que es muy versátil.
find
maneja los nombres de archivos extraños con *
ellos mejor que el for-loop? El bucle for maneja los archivos con *
multa, porque ha usado comillas dobles.
Si está utilizando bash
(el shell predeterminado), la extglob
opción de shell le permite usar una sintaxis extendida de coincidencia de patrones. Para habilitarlo, use el shopt
comando incorporado:
shopt -s extglob
(Incluyo esa línea en mi .bashrc
archivo).
Entre otras cosas, otorga acceso al !()
operador, que coincide con cualquier patrón que no se encuentre dentro de los elementos parentales. Para su propósito:
rm !(filename).gif
Hay más información disponible en man bash
"Coincidencia de patrones".
extglob
debe habilitarse, pero no pasa nada malo si está deshabilitada (en ese caso, esto simplemente no funciona). Y parece estar habilitado de manera predeterminada, aunque no tengo shopt -s extglob
ninguno de mis archivos de configuración (o los globales). Si hay una explicación simple de por qué me funciona de manera inmediata, puede agregarla a esta respuesta; o puedo publicar una nueva pregunta.
Abra una Terminal con Ctrl+ Alt+ Ty escriba:
find . -type f -name "*.gif" -and -not -name "filename.gif" -exec rm -vf {} \;
La diferencia entre -delete
y -exec rm -vf {} \;
es que con la segunda opción, podrá ver qué archivos se han eliminado, debido a la -v
bandera. Eso es algo que no se puede hacer con la -delete
opción. ( -name -delete
Imprimirá los nombres de archivo, pero rm
con -v
revela si cada archivo fue exitosamente eliminado.)
Ahí está la GLOBIGNORE
variable. De man 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.
Entonces, una forma simple es establecer GLOBGINORE
el nombre de archivo en cuestión:
$ 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
Entonces, en tu caso:
GLOBIGNORE=filename.gif; rm *.gif
Por supuesto, dado que GLOBIGNORE
contiene patrones, puede usarlo siempre que desee excluir un patrón:
$ GLOBIGNORE='[a-c].png'; echo *.png
d.png
$ touch bd.png; GLOBIGNORE='?.png'; echo *.png
bd.png
Una ventaja (?!) GLOBIGNORE
Es que su configuración excluye automáticamente .
y..
de ser emparejado, y permite 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.
Entonces, una forma simple de eliminar todos los archivos y carpetas en un directorio:
GLOBIGNORE=.; rm -r *
El *
coincidirá con nombres de archivo que comienzan con .
, ya GLOBIGNORE
habilitada dotglob
, pero no va a coincidir .
o ..
, por lo que no afectará el directorio padre de esa manera.