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).