¿Por qué el comando `find -type d -exec rmdir {} \;` produce el mensaje "No existe tal archivo o directorio"?

¿Por qué el comando `find -type d -exec rmdir {} \;` produce el mensaje "No existe tal archivo o directorio"?

Para fines de prueba, creé los siguientes directorios.

user@linux:~$ mkdir dir0{1..3}

user@linux:~$ ls -l
total 12K
drwxr-xr-x 2 user user 4.0K Mei  31 10:45 dir01
drwxr-xr-x 2 user user 4.0K Mei  31 10:45 dir02
drwxr-xr-x 2 user user 4.0K Mei  31 10:45 dir03
user@linux:~$ 

Luego lo quité confind -exec

user@linux:~$ find -type d -exec rmdir {} \;
rmdir: failed to remove '.': Invalid argument
find: ‘./dir02’: No such file or directory
find: ‘./dir01’: No such file or directory
find: ‘./dir03’: No such file or directory
user@linux:~$ 

Los directorios fueron eliminados, lo verifiqué.

user@linux:~$ ls -l
total 0
user@linux:~$ 

Mis preguntas son:

1) No entiendo por qué estaban ahí los mensajes. ¿Alguna idea de por qué?

rmdir: failed to remove '.': Invalid argument
find: ‘./dir02’: No such file or directory

No veo este tipo de error conrmdir

user@linux:~$ mkdir dir0{1..3}
user@linux:~$ 

user@linux:~$ ls -l
total 12K
drwxr-xr-x 2 user user 4.0K Mei  31 22:58 dir01
drwxr-xr-x 2 user user 4.0K Mei  31 22:58 dir02
drwxr-xr-x 2 user user 4.0K Mei  31 22:58 dir03
user@linux:~$ 

user@linux:~$ rmdir *
user@linux:~$ 

user@linux:~$ ls -l
total 0
user@linux:~$ 

2) ¿Es posible eliminar estos mensajes?

Respuesta1

Obtiene esos errores de "No existe tal archivo o directorio" findporque findestá intentando ingresar a directorios que acaba de eliminar. De forma predeterminada, aplicará sus acciones a todos los elementos coincidentes en el directorio que está visitando actualmente antes de continuar con los subdirectorios.

Agregue -deptha la invocación de findpara realizar finduna búsqueda profunda de sus rutas de búsqueda, lo que a su vez significa que si ejecuta rmdiren un directorio, ya lo habrá visitado y no intentará visitarlo nuevamente.

La -depthopción está implícita cuando se usa -deletepor este motivo (en implementaciones de findthat has -delete).

find . -depth -type d -exec rmdir {} \;

-depthes una opción estándar para la findutilidad.

Tenga en cuenta que rmdirsólo funciona en directorios vacíos. Si tiene muchos directorios que no están vacíos, el comando anterior generará muchos mensajes de error.

En su lugar, si findlo admite, utilice -empty:

find . -type d -empty -delete

Esto eliminaría directorios vacíos.

Con un findque no tiene el no estándar -deleteni -emtpy:

find . -depth -type d -exec sh -c '
    for dirpath do
        set -- "$dirpath"/*
        [ ! -e "$1" ] && rmdir "$dirpath"
    done' sh {} +

Esto probaría si los directorios encontrados estaban vacíos y, si lo estuvieran, se eliminarían.

Es un código largo para evitar ver algunos mensajes de error debido a que los directorios no están vacíos, pero cualquier mensaje de error quesonEs de esperar que los archivos producidos sean más interesantes de observar, ya que probablemente sean errores de "permiso denegado". Redirigir los errores al /dev/nullprimer findcomando en la parte superior habría ocultado dichos errores.

Respuesta2

Lo que presumiblemente sucede es que, con la -exec ... \;construcción, find hace su trabajo paso a paso:

  • recorrer el árbol de directorios, encontrar entradas que coincidan -type dy
  • ejecute rmdirdichas entradas tan pronto como las encuentre.

Esto significa que, en su ejemplo, find buscará en dir01, lo tendrá en cuenta como un directorio para ingresar más tarde, luego rmdirlo ejecutará y luego, al intentar recurrir a dir01, fallará porque ya no existe.

Ejecutar with -exec rmdir {} +debería ayudar en este caso: rmdir dir01 dir02 dir03se emitirá una única llamada a. Esto elimina los últimos tres mensajes de error.

El mensaje de error se debe .a que, bueno ., el directorio actual es de hecho un directorio, pero no uno que rmdirse pueda eliminar, porque no está vacío. Utilízalo -min-depthpara dejar de considerarlo, haciendo el comando:

find -mindepth 1 -type d -exec rmdir {} +

Esto no es perfecto; Los directorios anidados o una gran cantidad de directorios coincidentes aún podrían causar que se impriman mensajes de error, pero esto debería funcionar en el caso simple de la pregunta.

información relacionada