Otra respuesta es forzar xargs
para procesar los comandos en lotes. Por ejemplo a delete
los archivos 100
a la vez, cd
en el directorio y ejecuta esto:
echo *.pdf | xargs -n 100 rm
tl;dr
Es una limitación del kernel en el tamaño del argumento de la línea de comando. Usa un for
bucle en su lugar.
Origen del problema
Este es un problema del sistema, relacionado con execve
y ARG_MAX
constante. Hay mucha documentación al respecto (ver man execve, wiki de debian, detalles de ARG_MAX).
Básicamente, la expansión produce un comando (con sus parámetros) que supere el ARG_MAX
limit.On kernel 2.6.23
, el límite se estableció en 128 kB
. Esta constante ha sido incrementada y puedes obtener su valor ejecutando:
getconf ARG_MAX
# 2097152 # on 3.5.0-40-generic
Solución:Usar for
Bucle
Usa un for
loop como se recomienda en BashFAQ/095 y no hay límite excepto por RAM/espacio de memoria:
Realice una ejecución en seco para asegurarse de que eliminará lo que espera:
for f in *.pdf; do echo rm "$f"; done
Y ejecutarlo:
for f in *.pdf; do rm "$f"; done
Además, este es un enfoque portátil ya que glob tiene un comportamiento fuerte y consistente entre los shells (parte de la especificación POSIX).
Solución:Usar find
Si insistes, puedes usar find
pero realmente no uses xargs ya que "es peligroso (roto, explotable, etc.) al leer entradas no delimitadas por NUL" :
find . -maxdepth 1 -name '*.pdf' -delete
Usando -maxdepth 1 ... -delete
en lugar de -exec rm {} +
permite find
simplemente ejecutar el sistema requerido se llama a sí mismo sin usar un proceso externo, por lo tanto, más rápido (gracias al comentario de @chepner).
Referencias
- Obtengo "Lista de argumentos demasiado larga". ¿Cómo puedo procesar una lista grande en trozos? @ borde de lana
- execve(2) - página del manual de Linux (busque ARG_MAX);
- Error:lista de argumentos demasiado larga @ wiki de Debian;
- ¿Por qué aparece "/bin/sh:lista de argumentos demasiado larga" cuando paso argumentos citados? @ superusuario
find
tiene un -delete
acción:
find . -maxdepth 1 -name '*.pdf' -delete
La razón por la que esto ocurre es porque bash en realidad expande el asterisco a cada archivo coincidente, produciendo una línea de comando muy larga.
Prueba esto:
find . -name "*.pdf" -print0 | xargs -0 rm
Advertencia: esta es una búsqueda recursiva y también encontrará (y eliminará) archivos en subdirectorios. Agrega -f
al comando rm solo si está seguro de que no desea confirmación.
Puede hacer lo siguiente para que el comando no sea recursivo:
find . -maxdepth 1 -name "*.pdf" -print0 | xargs -0 rm
Otra opción es usar el -delete
de find bandera:
find . -name "*.pdf" -delete