Shell script: borrar archivos excepto una lista

Buenas. Nada, a ver si aprendo alguna cosilla más. Tengo que borrar todos los archivos de un directorio excepto los de una lista, algo sencillo. Lo tengo hecho de esta forma:
LISTA="|archivo1|otro_archivo|otro_archivo_más|a e i o u.dat|etcétera|"

for i in * ; do
   if [[ $( echo $LISTA | grep "|$i|" ) = "" ]] then
      rm $i
   fi   
done
Funcionar, funciona bien, pero no me acaba de gustar mucho, así que me preguntaba si habría otra forma más "elegante".

Y ya aparte, aunque no sé si es un tema que interesa, se podría hacer un hilo de shell script con dudas y "pruebas", para que aprendamos un poco todos. Alguna vez he visto algo parecido en otros foros pero no por aquí.
Y si haces el for de i a "resto de archivos"?
Me pondria, pero estoy vaguisimo x'D
Ugh.... varias cosas:

1) ¿Qué ocurre si un nombre de fichero contiene '|'?
2) No uses echo | blah, puede darte alguna que otra sorpresa.
3) Supón lo siguiente:

LISTA="a|c"


Y el directorio contiene los siguientes ficheros:

a
a b
c


En fin.... food for thought.

- ferdy
No entiendo lo que propones e-Minguez.

En cuanto al separador, podría cambiarse por / y ya no habría problema, porque los archivos no pueden contener / en el nombre. El caso es que donde lo usaré como mucho habrá espacios en los nombres, por eso no le he dado muchas vueltas a ese asunto.

Si no uso "echo a | grep blah", ¿cómo compruebo si una cadena está contenida en otra? Bueno ya buscaré esto, supongo que habrá cien formas.

Respecto al punto 3 de Ferdy, los archivos "a" y "c" los detectaría, el "a b" no y lo borraría. Eso ya lo había pensado, si un archivo a borrar tenía el nombre contenido en el de un archivo de la lista, por eso hago grep "|$i|" y la lista empieza y termina con los separadores. No sé si intentas que vea otra cosa que no veo.

Gracias por los comentarios
Respecto al punto 3 de Ferdy, los archivos "a" y "c" los detectaría, el "a b" no y lo borraría. Eso ya lo había pensado, si un archivo a borrar tenía el nombre contenido en el de un archivo de la lista, por eso hago grep "|$i|" y la lista empieza y termina con los separadores. No sé si intentas que vea otra cosa que no veo.


¿Seguro que lo has probado?

Sobre find, si y no: http://www.opengroup.org/onlinepubs/009695399/utilities/find.html . Depende de la situación puede interesar o no. De todos modos, ambos métodos pueden ser horrorosos en caso de tener que comprobar varios cientos de ficheros en varios miles de directorios.... también dependerá del volumen de datos con el que tratar.

- ferdy
No lo había probado porque la lista no podría ser "a|c", sería "|a|c|" de la forma en que lo he hecho. Pero vamos, que lo acabo de probar y veo el error con los espacios, con rm "$i" solucionado, gracias.

Estoy mirando find, aunque no sé cómo hacer que coja bien la lista, pero ya lo sacaré. En mi caso, como mucho habría unos 30 ó 40 archivos en el directorio.
Si de verdad estuviese en un entorno que sólo dispusiese de un find POSIX siempre podría tirar de "! \( -name -o -name pencil -o -name \)" creando la lista a partir de un array (suponiendo que una shell POSIX soporte arrays... si no de cualquier otra forma).

Para la expresión regular con variar palabras, es sólo "(||)". Escapando lo que necesites.
Si de verdad estuviese en un entorno que sólo dispusiese de un find POSIX siempre podría tirar de "! \( -name -o -name pencil -o -name \)" creando la lista a partir de un array (suponiendo que una shell POSIX soporte arrays... si no de cualquier otra forma).


Excepto que rápidamente llegarías al límite de argumentos :)

Anyway, suponer GNU-find no es tanto suponer... parece sano.

- ferdy
El límite de argumentos es de algún estándar? Linux lo solucionó hace poco.
No que yo sepa, por lo que sé, es bastante arbitrario.

- ferdy
Por lo visto en Linux está solucionado desde la 2.6.23-rc
http://article.gmane.org/gmane.linux.kernel/571977
Yo es que para hacer cosas así soy más bruto y más chapuzas: creo un directorio temporal, muevo los archivos de la lista ahí, me cepillo el resto, vuelvo a poner los de la lista en su sitio y me cargo el temporal. xD

Un saludo.
12 respuestas