Lo más probable es que eliminar el directorio de trabajo actual no sea una buena idea.
Alexej Magura
Acordó - me gusta el comportamiento por defecto, pero no es consistente con, por ejemplo, find . -print.
mbroshi
@AlexejMagura aunque simpatizo, no veo por qué eliminar el directorio actual debería ser diferente de eliminar un archivo abierto. El objeto permanecerá vivo hasta que exista una referencia a él y luego se recolectará la basura. Puedes hacerlo cd ..; rm -r dircon otro caparazón con una semántica bastante clara ...
Rmano
@Rmano, esto es cierto: es algo que no haría en principio: solo sube un directorio y luego elimina el directorio actual. No estoy completamente seguro de por qué es tan importante, aunque he tenido algunas desgracias con el directorio actual que ya no existe, como las rutas relativas que ya no funcionan, pero siempre puedes salir usando una ruta absoluta, pero Una parte de mí dice que no es una buena idea en general.
Alexej Magura
Respuestas:
29
Los miembros de lo findutilssaben , es compatible con * BSD:
Una de las razones por las que omitimos la eliminación de "." es por compatibilidad con * BSD, donde se originó esta acción.
Las NOTICIAS en el código fuente de findutils muestran que decidieron mantener el comportamiento:
#20802: If -delete fails, find's exit status will now be non-zero. However, find still skips trying to delete ".".
[ACTUALIZAR]
Dado que esta pregunta se convirtió en uno de los temas candentes, me sumergí en el código fuente de FreeBSD y salí a la luz por una razón más convincente.
Porque su findcomando regresa .como resultado. Desde la página de información de rm:
Cualquier intento de eliminar un archivo cuyo último componente de nombre de archivo es '.' o '..' se rechaza sin ninguna solicitud, como lo ordena POSIX.
Entonces, parece que findsolo se apega a las reglas POSIX en este caso.
Como debería: POSIX es el rey, además de eliminar el directorio actual podría causar algunos problemas muy grandes dependiendo de la aplicación principal y qué no. ¿Qué tal si el directorio actual fuera /var/logy lo ejecutaras como root, pensando que eliminaría todos los subdirectorios y también eliminaría el directorio actual?
Alexej Magura
1
Esa es una buena teoría, pero la manpágina finddice: "Si la eliminación falla, se emite un mensaje de error". ¿Por qué no se imprime ningún error?
mbroshi
1
@AlexejMagura Extracción del directorio actual fina obras en general: mkdir foo && cd foo && rmdir $(pwd). Está eliminando .(o ..) eso no funciona.
El significado de eliminar pathname / dot no está claro, porque el nombre del archivo (directorio) en el directorio principal que se eliminará no está claro, particularmente en presencia de múltiples enlaces a un directorio.
Si bien 林果 皞 y Thomas ya dieron buenas respuestas sobre esto, creo que sus respuestas olvidaron explicar por qué este comportamiento se implementó en primer lugar.
En su find . -deleteejemplo, eliminar el directorio actual suena bastante lógico y sensato. Pero considere:
$ find . -name marti\*
./martin
./martin.jpg
[..]
¿ .Todavía te parece lógico y sensato eliminar ?
La eliminación de un directorio no vacío es un error, por lo que es poco probable que pierda datos con esto find(aunque podría hacerlo rm -r), pero su shell tendrá su directorio de trabajo actual configurado en un directorio que ya no existe, lo que puede generar confusión. y comportamiento sorprendente:
$ pwd
/home/martin/test
$ rm -r ../test
$ touch foo
touch: cannot touch 'foo': No such file or directory
No eliminar el directorio actual es simplemente un buen diseño de interfaz y cumple con el principio de menor sorpresa.
find . -print
.cd ..; rm -r dir
con otro caparazón con una semántica bastante clara ...Respuestas:
Los miembros de lo
findutils
saben , es compatible con * BSD:Las NOTICIAS en el código fuente de findutils muestran que decidieron mantener el comportamiento:
[ACTUALIZAR]
Dado que esta pregunta se convirtió en uno de los temas candentes, me sumergí en el código fuente de FreeBSD y salí a la luz por una razón más convincente.
Veamos el código fuente de la utilidad de búsqueda de FreeBSD :
Como puede ver, si no filtra punto y punto-punto, alcanzará la
rmdir()
función C definida por POSIXunistd.h
.Haga una prueba simple, rmdir con argumento punto / punto-punto devolverá -1:
Echemos un vistazo a cómo POSIX describe rmdir :
No se dio ninguna razón por qué
shall fail
.Encontré
rename
explicar algunas razones :¿Rutas cíclicas del sistema de archivos ?
Miro el lenguaje de programación C (2da edición) y busco el tema del directorio, sorprendentemente encontré que el código es similar :
Y el comentario!
"bucle para siempre" , esto es lo mismo que
rename
describirlo como "rutas cíclicas del sistema de archivos" arriba.Modifico ligeramente el código y lo hago correr en Kali Linux basado en esta respuesta :
Veamos:
Funciona correctamente, ahora qué pasa si comento las
continue
instrucciones:Como puede ver, tengo que usar Ctrl+ Cpara eliminar este programa de bucle infinito.
El directorio '..' lee su primera entrada '..' y se repite para siempre.
Conclusión:
GNU
findutils
intenta ser compatible con lafind
utilidad en * BSD .find
La utilidad en * BSD utiliza internamente larmdir
función C compatible con POSIX que no está permitida dot / dot-dot.La razón de
rmdir
no permitir dot / dot-dot es evitar las rutas cíclicas del sistema de archivos.El lenguaje de programación C escrito por K&R muestra el ejemplo de cómo punto / punto-punto conducirá a un programa de bucle para siempre.
fuente
Porque su
find
comando regresa.
como resultado. Desde la página de información derm
:Entonces, parece que
find
solo se apega a las reglas POSIX en este caso.fuente
/var/log
y lo ejecutaras como root, pensando que eliminaría todos los subdirectorios y también eliminaría el directorio actual?man
páginafind
dice: "Si la eliminación falla, se emite un mensaje de error". ¿Por qué no se imprime ningún error?mkdir foo && cd foo && rmdir $(pwd)
. Está eliminando.
(o..
) eso no funciona.La llamada al sistema rmdir falla con EINVAL si el último componente de su ruta de argumento es
"."
. Está documentado en http://pubs.opengroup.org/onlinepubs/009695399/functions/rmdir.html y la justificación del comportamiento es:fuente
Llamar
rmdir(".")
como una llamada al sistema no funcionó cuando lo intenté, por lo que ninguna herramienta de nivel superior puede tener éxito.Debe eliminar el directorio a través de su nombre real, no su
.
alias.fuente
Si bien 林果 皞 y Thomas ya dieron buenas respuestas sobre esto, creo que sus respuestas olvidaron explicar por qué este comportamiento se implementó en primer lugar.
En su
find . -delete
ejemplo, eliminar el directorio actual suena bastante lógico y sensato. Pero considere:¿
.
Todavía te parece lógico y sensato eliminar ?La eliminación de un directorio no vacío es un error, por lo que es poco probable que pierda datos con esto
find
(aunque podría hacerlorm -r
), pero su shell tendrá su directorio de trabajo actual configurado en un directorio que ya no existe, lo que puede generar confusión. y comportamiento sorprendente:No eliminar el directorio actual es simplemente un buen diseño de interfaz y cumple con el principio de menor sorpresa.
fuente