Eliminar archivos y directorios por sus nombres. El fichero o directorio no existe

32

Necesito eliminar todos los datos compilados:

  • directorios llamados build,
  • directorios llamados obj,
  • * .so archivos.

Escribi un comando

find \( -name build -o -name obj -o -name *.so \) -exec rm -rf {} \;

que recorre todos los directorios de forma recursiva y elimina todo lo que necesito.

¿Por qué tengo esa salida al final? Tal vez debería escribir un comando diferente.

find: `./3/obj': No such file or directory
find: `./3/build': No such file or directory
find: `./1/obj': No such file or directory
find: `./1/build': No such file or directory
find: `./2/obj': No such file or directory
find: `./2/build': No such file or directory
Maksim Dmitriev
fuente
en que sistema eres siempre debe usar findasí find /search_directory optionsomitir el directorio de búsqueda no es una buena idea
Kiwy
La eliminación automática como esta es una mala idea. Puede hacer que un script le proporcione candidatos, que luego debe mirar para asegurarse de que no está eliminando nada importante o necesario para el sistema. No eres explícito donde estás ejecutando esto. Si solo está haciendo esto en un espacio de usuario, supongo que no puede hacer mucho daño, pero debe asegurarse de no hacerlo accidentalmente en un área del sistema. Definitivamente desea ejecutar un script como usuario.
Faheem Mitha
@ Kiwy, @ FaheemMitha, el comando solo se usará en el proyecto directoty; No hará ningún daño allí.
Maksim Dmitriev
Relacionado: stackoverflow.com/questions/22462124/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Respuestas:

54

Use -pruneen los directorios que va a eliminar de todos modos para decirle que findno se moleste en tratar de encontrar archivos en ellos:

find . \( -name build -o -name obj -o -name '*.so' \) -prune -exec rm -rf {} +

También tenga en cuenta que *.sodebe citarse, de lo contrario, el shell puede expandirlo a la lista de .soarchivos en el directorio actual.

El equivalente de su -regextipo GNU sería:

find . \( -name build -o -name obj -o -name '*?.so' \) -prune -exec rm -rf {} +

Tenga en cuenta que si va a usar la sintaxis específica de GNU, también podría usarla en -deletelugar de -exec rm -rf {} +. Con -delete, GNU se findenciende -depthautomáticamente. No ejecuta comandos externos, por lo que de esa manera, es más eficiente y también es más seguro, ya que elimina la condición de carrera en la que alguien puede hacer que elimines los archivos incorrectos cambiando un directorio a un enlace simbólico entre el tiempo findencuentra un archivo y lo rmelimina (ver info -f find -n 'Security Considerations for find'para más detalles).

find . -regextype posix-egrep -regex '.*/((obj|build)(/.*)?|.+\.so)' -delete
Stéphane Chazelas
fuente
-deletetambién maneja mejor cosas como espacios
Izkata
@Izkata, no mejor que el -exec rm -rf {} +que tampoco tiene problemas con ellos.
Stéphane Chazelas
@StephaneChazelas, estoy confundido {}, ¿deberían citarse o no? Parece que funciona sin comillas, pero GNU Findutils Manual utiliza, '{}'por ejemplo. ¿Podrías aclararlo por favor?
grebneke
1
@grebneke, creo que hay una publicación en algún lugar que podría necesitar citas de reclamos en versiones muy antiguas de csh, pero nunca pude verificar ese reclamo. No se necesitan en ningún caparazón moderno que yo sepa. Definitivamente no son requeridos por POSIX. Los ejemplos POSIX no los usan.
Stéphane Chazelas
3
Y -deleteno se puede usar con directorios.
St0rM
8

Supongo que la razón es que findprimero elimina el árbol del directorio e intenta verificar el contenido del directorio, lo que obviamente no es el mejor orden posible. Puede forzar finda verificar el contenido primero:

find . -depth ...

Debe considerar usar -deletepara archivos y -exec rmdirdirectorios.

Hauke ​​Laging
fuente
0

Mi solución.

find . -regextype posix-egrep -regex ".*/(obj|build|.+\.so)" -prune -exec rm -rf {} +

+ vs \; en el comando -exec

Maksim Dmitriev
fuente
Eso no siempre va a funcionar, solo si no hay límites entre las ejecuciones dentro de un directorio eliminado.
Gilles 'SO- deja de ser malvado'
@Gilles, ¿qué significa "límite entre ejecuciones"?
Maksim Dmitriev
1
-exec … {} +ejecuta el comando para múltiples archivos a la vez, tantos como quepan en la línea de comando. Si hay demasiados archivos (o más precisamente si la longitud total de las rutas es demasiado larga), findejecutará múltiples instancias rmy, por lo tanto, puede terminar eliminando un directorio que está atravesando. Es menos probable con +que con ;, pero +no resuelve el problema.
Gilles 'SO- deja de ser malvado'