Recientemente me enfrenté a la tarea de eliminar todos los archivos / carpetas en un directorio, excepto aquellos que coinciden con un patrón específico. Así que preparé un comando unix de una sola línea para hacer el trabajo. ¿Debe ser solo una línea? Supongo que no, ¡pero definitivamente es más genial así!
Si bien el problema es bastante simple, me sorprendió un poco lo compleja que resultó ser mi solución. Aquí está el comando que usé; NOTA: esta es una solución pobre porque no maneja nombres de archivo que contengan caracteres de avance de línea (lo que no importó en mi situación).
ls | grep -v PATTERN | xargs -n1 -IREPLACE rm -rf REPLACE
No utilicé el comando "buscar" porque no quiero volver a las carpetas que coinciden con PATTERN. Por ejemplo, considere la siguiente estructura de archivos:
file_foo.txt
first_dir
|
+--> contents
+--> ...
foo_dir
|
+--> anotherfile.txt
+--> morefiles.log
foo_file.txt
somefile.txt
El uso del patrón "foo" solo debe eliminar "first_dir" (y su contenido, por supuesto) y "somefile.txt" ( no "anotherfile.txt" o "morefiles.log").
Pregunta, ¿hay formas mejores (más elegantes y correctas) de lograr esto?
EDITAR:
Hace poco me llamó la atención que "encontrar" puede ser una mejor opción:
find * -maxdepth 0 ! -name PATTERN -print0 | xargs -0n1 rm -rf
Esta solución maneja correctamente las rutas que contienen caracteres de avance de línea.
fuente
Respuestas:
Los siguientes ejemplos tienen un
echo
prefijo para que pueda probar los patrones antes de usarlos. Retire elecho
para activar elrm -rf
. Sustituirrm -ri
para solicitar confirmación.ksh tiene una extensión de coincidencia negativa para su globbing:
La misma sintaxis está disponible en bash si configura la
extglob
opción:zsh tiene su propia sintaxis para esto:
También puede usar la sintaxis de estilo ksh :
fuente
shopt -s extglob
a mi archivo .bashrc, por lo que ahora es un trazador de líneas). ¡Perfecto! Prometo un voto positivo tan pronto como mi reputación lo permita.Aquí hay otra
find
solución. No estoy seguro de que esto tenga una ventaja real sobre la suya, pero no lo necesitaxargs
y permite la rara posibilidad de que * se expanda a demasiados nombres.También agregué
-type f
para que no intentara eliminar directorios.Advertencia:
-delete
es poderoso. Le di 0 permisos a uno de mis archivos de prueba y el comando anterior lo eliminó sin dudarlo.fuente
-delete
con-print
para ver si está buscando los archivos que desea. Si todo está bien, use el historial de comandos (por ejemplo, presione el botón arriba) para volver al comando anterior y asegurarse de que está trabajando con los mismos filtros de búsqueda.find -delete
no eliminará directorios no vacíos. Observe también quefind -maxdepth 1
coincide con "." (directorio actual) que es realmente malo. Aunque me gusta su idea de eliminarxargs
, uno podría usarfind -exec
alternativamente.find * -maxdepth 0 ! -name PATTERN -exec rm -rf '{}' \;
En su lugar, podría usar este ejemplo de script de rebol http://askcodegeneration.com/keep-subversion/, que es mucho más comprensible y que puede gestionar la interacción del usuario, como la selección y confirmación de carpetas:
fuente