Digamos que tengo un directorio con varios archivos, todos los cuales son archivos binarios (archivos sin extensiones declaradas) y archivos fuente (.c extensión). Hago esto:
$ ls
y obtener:
README.md hello-world.c hello-world get-name.c get-name
y quiero enumerar solo archivos con extensiones específicas (diga ambos .c y .md ), yo sí:
ls *.c *.md
¡y eso está bien!
Pero, ¿y si ahora quiero eliminar todos los archivos que no tener un .c o .md extensión, ¿cómo puedo hacer esto?
Sé cómo hacerlo con archivos cuyas extensiones conozco, como:
ls *.c *.md | xargs rm
Pero, ¿cómo le digo a la línea de comando que elimine los archivos que NO coincide con mis criterios?
Respuesta aceptada:
Usa find :
find -maxdepth 1 ! -name "*.c" -print0 | xargs -0 ...
Tenga en cuenta que -maxdepth , -print0 , -r y -0 se encuentran en algunos find implementaciones (fueron introducidas por GNU find /xargs ) pero no están especificados por POSIX. Otra forma es, como menciona Stéphane en su comentario, usando el -exec acción de buscar:recuerda usar el comando -exec command {} + forma, ya que reduce drásticamente el número de invocaciones de command (tiene que permitir la sintaxis donde los nombres de los archivos se colocan al final, o de lo contrario, debe envolver el comando command dentro de un sh -c llamar).
Alternativamente grep la salida de ls
ls | grep -v ".c$" | xargs ...
Puede filtrar varias extensiones con expresiones regulares:
... | grep -v ".(c|md)$" | ...
con expresiones regulares extendidas:
... | grep -Ev ".(c|md)$" | ...
con la opción de cadenas fijas (¡no coincidirá solo al final del nombre del archivo!):
... | grep -vF ".c
.md" | ...
o encadenando más grep s:
... | grep -v ".c$" | grep -v ".md$" | ...
Dicho esto, find es probablemente la mejor opción, ya que con -print0 maneja todos los caracteres posibles en los nombres de archivo que podrían necesitar escapar de otra manera (siempre que su find y xargs son capaces de trabajar con cadenas terminadas en NULL, p. las herramientas GNU lo son).