¿Cómo puedo eliminar todos los archivos de un directorio cuando informa "Lista de argumentos demasiado larga"

11

Tengo un directorio con un par de cientos de miles de archivos.

Quiero eliminar todos los archivos, pero rm * -f informa: "lista de argumentos demasiado larga"

¿Cuál es la mejor manera de limpiar este directorio?

Brent
fuente
Relacionado, semi-duplicado: unix.stackexchange.com/questions/37329/…
Denilson Sá Maia

Respuestas:

11

En el caso de que no pueda eliminar el directorio, siempre puede usar find.

find . -maxdepth 1 -type f -exec rm -f {} \;

Eso eliminará todos los archivos en el directorio actual, y solo el directorio actual (no los subdirectorios).

escabroso
fuente
casi perfecto (vea mi publicación también)
asdmin
2
En Linux, puede hacerlo aún más rápido usando "+" en lugar de "\;". Eso hará que elimine más archivos por "rm" de una vez.
Thomas
55
Incluso más rápido: find dir/to/delete -delete(no genera un rmproceso por archivo para eliminar).
Morten Siebuhr
Morten: Nunca mencionó querer eliminar el directorio en sí, dijo onky los archivos. find dir/to/delete -type f -delete
richo
21
encontrar . -maxdepth 1 -tipo f -exec rm -f {} \;

simplemente lleva demasiado tiempo (un exec de rm por archivo).

Este es mucho más eficiente:

encontrar . -maxdepth 1 -tipo f -print0 | xargs -r0 rm -f

ya que toma tantos nombres de archivos como argumentos para rm tanto como sea posible, luego ejecuta rm con la próxima carga de nombres de archivos ... puede suceder que rm solo se llame 2 o 3 veces.

asdmin
fuente
55
Me alegra ver a alguien saber cómo funciona find ... También considere con el nuevo gnu find la acción -delete o el comando -exec {} + que actúa como xargs. Consulte la sección Acciones de 'man find'.
Kyle Brandt el
No sabía sobre -exec cmd {} +. Eso parece bastante útil. Un poco más genérico que -delete :)
David Pashley
-Eliminar puede estar bien, pero personalmente prefiero los comandos que se pueden usar en una variedad de máquinas. Solaris sistemas con los que trabajo son mayores, por lo -delete no funcionaría en ellos
asdmin
2
Agregar ioniceantes rmes una buena idea si otras personas usan la computadora al mismo tiempo.
Hubert Kario
6

Ambos resolverán el problema. Hay un análisis del rendimiento respectivo de cada técnica aquí .

find . -name WHATEVER -exec rm -rf {} \;

o

ls WHATEVER | xargs rm -rf

El problema se debe a que bash expande "*" con cada elemento en el directorio. Ambas soluciones funcionan a través de cada archivo a su vez.

Cooperativas
fuente
2
La solución de búsqueda es más lenta con muchos archivos porque invoca el comando rm para cada archivo. La solución xargs es más rápida, pero solo funciona cuando los nombres de los archivos no contienen espacios (de lo contrario, necesita GNU find y find . -print0 | xargs -0 rm).
robado
"find. -name WHATEVER -print0 | xargs -0 rm -rf" será más eficiente. find bifurcará un rm para cada archivo, donde xargs lo reducirá al mínimo. Necesita los -print0 y -0 para hacer frente a los archivos con espacios. Probablemente también desee usar -depth en find, por lo que realiza una búsqueda profunda en primer lugar.
David Pashley el
El comando ls no funcionará, ya que eso también devuelve "lista de argumentos demasiado larga"
Brent
2
Estás haciendo " ls *", y el " *" se expande a la lista de argumentos de que tu shell se queja de ser demasiado largo. Haga " ls ." en su lugar (o suba un nivel de directorio y haga " ls [dirname]").
James Sneeringer
la segunda línea de comando (ls WHATEVER | xargs rm -rf) no funcionaría por la misma razón que la pregunta no funcionó: WHATEVER sería sustituido por shell a una longitud superior
asdmin
3

Pude hacer esto haciendo una copia de seguridad de un nivel:

cd ..

Y corriendo:

rm directory name -rf

Y luego volver a crear el directorio.

Brent
fuente
1
funciona solo si no tiene que tener el directorio de forma permanente y todos los archivos y directorios se eliminarán de forma recursiva. La mayoría de los casos en mi vida, de esta manera no habría funcionado.
asdmin
2

Todas estas invocaciones de hallazgos son muy agradables, pero rara vez recuerdo exactamente la nomenclatura necesaria cuando tengo prisa: en su lugar, uso ls. Como alguien menciona, ls. funcionaría pero prefiero ls -1 como en:

ls -1 | xargs -n 100 rm -rf

La figura -n xxx es bastante segura para jugar, ya que exceder el máximo se corregirá automáticamente (si se excede size-max; vea -s) o si se excede el args-max para una aplicación, generalmente será bastante obvio.

Debe tenerse en cuenta que grep es útil para insertar en el medio de esta cadena cuando solo desea eliminar un subconjunto de archivos en un directorio grande y, por cualquier razón, no desea utilizar find.

Esta respuesta asume que está utilizando las utilidades principales de Gnu para sus ls, xargs, etc.

rixtertech
fuente
¿Funcionará esto con un directorio que sea demasiado grande para que funcione "ls"? (mismo error - lista de argumentos demasiado larga)
Brent
Sí Brent: solo asegúrese de no utilizar una especificación de archivo cuando invoque ls. Use solo el -1 (guión uno) como se muestra arriba. Y como se explicó anteriormente, use grep después de ls si necesita emparejar la lista de archivos. Si obtiene el error "demasiado largo" después de asegurarse de que no está usando ningún comodín con ls, entonces quizás xargs se esté quejando. Use 'xargs -n 5' en lugar de 'xargs -n 100' y definitivamente debería estar seguro, aunque sea un poco más lento.
rixtertech
1

Puede usar la -exec +opción para encontrar cuál intentará ejecutar rm las menos veces posible, lo que podría ser más rápido.

find . -type f -exec rm '{}' +
Rory
fuente
0

Aquí hay una versión para eliminar una gran cantidad de archivos cuando el sistema necesita permanecer receptivo.

Funciona emitiendo trabajo en lotes pequeños (100 archivos por defecto) y esperando un poco a que finalicen otros trabajos.

Funcionó de manera brillante para eliminar más de medio millón de archivos de un solo directorio en ext3. Imprime el porcentaje realizado como un pequeño bono

noOfFiles=`ls -U | wc -l`
n=0
while (ls -U | tail -n 100 | xargs rm -f); do 
   n=$((n+100));
   sync;
   echo -en "$((n*100/noOfFiles))%, ($n of $noOfFiles)\r";
   sleep 5;
done
Hubert Kario
fuente
0

Resuelve errores de "argumento demasiado largo" o "no se puede asignar memoria"

Esto hizo el truco en más de 220,000 archivos en la carpeta de sesión ...

Ventaja: comienza instantáneamente a eliminar archivos

ruta de CD / a / carpeta
ls -f | xargs rm -f -v

HAGA CLIC para la captura de pantalla de los archivos que se eliminan - (eliminó todos los archivos en ~ 15 minutos)

-f (después de ls) evita la clasificación previa

-v (después de rm) muestra cada archivo como eliminado

-f (después de rm) se abre paso sin solicitar mensajes en archivos protegidos contra escritura

Consejo: Cambie el nombre de la carpeta (por ejemplo, session a session_old) primero para evitar que se agreguen archivos autogenerados adicionales mientras intenta eliminar archivos. Puede rehacer el directorio original manualmente si no lo hace automáticamente, como en mi caso

kilcode
fuente
¿Qué hay de nuevo en su respuesta que faltaba de las anteriores?
user2233709