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 .keepextensió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 finden 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 -notoperador 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 findes 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 -inameen lugar de -namepara 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 -inamecoincidirá 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 -deleteprimero, antes de las otras expresiones! Verás que siempre pongo -deleteal final. Si lo pones al principio, se evaluaría primero, y todos los archivos debajo .(incluidos los archivos que no terminan en .gify 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 bashy shy para los comandos utilizados en estos ejemplos: mv, rm, [, y (especialmente) find.
find, que es muy versátil.
findmaneja 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 extglobopción de shell le permite usar una sintaxis extendida de coincidencia de patrones. Para habilitarlo, use el shoptcomando incorporado:
shopt -s extglob
(Incluyo esa línea en mi .bashrcarchivo).
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".
extglobdebe 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 extglobninguno 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 -deletey -exec rm -vf {} \;es que con la segunda opción, podrá ver qué archivos se han eliminado, debido a la -vbandera. Eso es algo que no se puede hacer con la -deleteopción. ( -name -deleteImprimirá los nombres de archivo, pero rmcon -vrevela si cada archivo fue exitosamente eliminado.)
Ahí está la GLOBIGNOREvariable. 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 GLOBGINOREel 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 GLOBIGNOREcontiene 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 (?!) GLOBIGNOREEs 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 GLOBIGNOREhabilitada dotglob, pero no va a coincidir .o .., por lo que no afectará el directorio padre de esa manera.