¿Por qué `cp` y` rm` tratan los directorios por separado?

10

¿Por qué las herramientas les gustan cpy rmtratan los directorios por separado de los archivos normales? Ambos requieren que el usuario especifique explícitamente que quiere un comportamiento recursivo, o de lo contrario no tratarán con directorios en absoluto.

Mi primera interacción (hace un tiempo) con las computadoras fue en un entorno Windows / GUI / apuntar y hacer clic / arrastrar y soltar, siempre parecía natural que estas operaciones se comportaran igual, independientemente del objetivo.

Este comportamiento me frustra particularmente cuando doy comandos con comodines. ¿Qué sucede si deseo eliminar todo en un directorio ( *) excepto los subdirs no vacíos ?

Solo puedo imaginar que esta es una especie de característica de seguridad para evitar que el usuario se dispare en el pie, pero esto contradice mi comprensión de algunos principios de Unix:

  • Unix no suele proteger al usuario de sí misma. Siempre ha asumido que el usuario sabe lo que está haciendo.
  • Para Unix todo es un archivo. ¿No es un directorio simplemente otro archivo? ¿Por qué son tratados de manera diferente?

Mis preguntas:

  • ¿Es este comportamiento derivado de una limitación técnica o es una elección deliberada?

Y en el caso de este último,

  • ¿Hay algún relato histórico de las razones que motivaron esta elección?
rahmu
fuente
Por rmlo menos, si lo desea ignorar la diferencia entre los archivos y directorios, se puede poner en su ~/.bashrcarchivo: alias rm='rm -r'.
BenjiWiebe
1
Vea también la pregunta diferente pero relacionada unix.stackexchange.com/questions/46066/…
derobert
1
No puede comparar cp y rm con el administrador de archivos de Windows. Inicie cmd.exe e intente copiar y borrar y compare el comportamiento.
ott--

Respuestas:

11

¿ Por qué el programa unix mv de Derobert no necesita la opción -R (recursiva) para directorios pero cp sí la necesita? básicamente responde a su pregunta: copiar o eliminar un archivo normal es diferente de hacer la misma operación con un directorio, porque para un directorio debe procesar todos los archivos contenidos en él. Por lo tanto, la operación es fundamentalmente diferente.

También vale la pena señalar que hay una utilidad especial rmdirque solo puede actuar en directorios vacíos. Sin verificar los hechos, esto lleva a la conclusión de que tal vez originalmente rmsolo pudo eliminar los no directorios y la eliminación profunda tuvo que lograrse mediante el uso recursivo rmpara vaciar directorios y luego rmdireliminarlos.

Peterph
fuente
rmdirtambién es el nombre de la llamada al sistema que se usó para eliminar un directorio. El directorio debe estar vacío para la llamada al sistema, y ​​la utilidad del mismo nombre es solo "front-end", similar al unlinkcomando y la utilidad.
jordanm
Exactamente, eso es lo que me lleva a creer que originalmente rmpodría no haber sido capaz de eliminar directorios (porque las utilidades de línea de comandos a menudo son envoltorios relativamente simples alrededor de las llamadas al sistema).
Peter
El título de mi pregunta podría inducir a error al pensar que estoy preguntando sobre los detalles técnicos. Estaba preguntando si es una elección deliberada. Me pregunto si soy el único que piensa que, desde el punto de vista del usuario final, este comportamiento es inconsistente. Estoy aceptando su respuesta porque indirectamente responde a mi pregunta: las limitaciones técnicas en los componentes internos de Unix (a nivel de syscall) parecen ser el origen de este comportamiento, y el legado probablemente nos impide hacerlo de otra manera hoy. ¿No se supone que los "envoltorios simples alrededor de las llamadas al sistema" nos dan comportamientos más inteligentes?
rahmu
2
Desde el punto de vista del usuario final, parece extraño, pero en realidad estabas preguntando por los motivos. :) En cuanto a los envoltorios, todo depende de cuán "simples" sean (y de lo que todavía quieres llamar "simple"). Modern rmdefinitivamente no es solo un simple contenedor (es capaz de eliminar archivos mroe a la vez y directorios). Si no le gusta darle la -ropción, use la funcionalidad de alias de su shell o cree su propio contenedor que lo coloque en su lugar (que sería más lento, pero independiente del shell que está utilizando).
Peter
2

En algunos sabores de UNIX, la página de manual de rm lo especifica como un comando para desvincular un archivo.
En UNIX, los archivos son objetos en el sistema de archivos llamados Inodes, sin nombres ni ubicaciones aparte de una ID en el sistema de archivos. Sus nombres son referencias a ellos en varios directorios, que son un tipo de archivo que indexa los archivos (o directorios, ya que son archivos) que figuran en él.
Al desvincular un archivo, el recuento de referencia del archivo disminuye, y cuando alcanza 0, de hecho se elimina, ya que el sistema de archivos lo marca como libre y sus bloques / extensiones también se marcan como libres.

Si tuvo la capacidad de ejecutar un directorio sin desvincular primero los archivos dentro de él, llegará a un punto donde tiene inodos referenciados en su sistema de archivos pero no se puede acceder por ningún medio normal.
Como hay una referencia a ellos según su recuento de referencias, no se marcan como eliminados y se convierten en archivos perdidos.
Esto se vuelve aún más complejo cuando los "archivos" perdidos son directorios, y como tal aumenta la cantidad potencial de almacenamiento perdido en el sistema de archivos.

Por lo tanto, se agregó rm -r, como una característica para facilitar la vida de los usuarios de UNIX, a expensas del "espíritu UNIX" estándar, ya que es más complejo que las utilidades clásicas de UNIX, ya que desciende a directorios y elimina archivos,

Además, en los primeros tiempos de UNIX, los sistemas no tenían mucha memoria, y el mapeo de la estructura recursiva de un directorio tenía una penalización de rendimiento, y a veces era imposible hacerlo sin dividir el trabajo.

cp, lee un archivo y lo copia, bloque por bloque. Si copiara un directorio de la misma manera que un archivo, agregaría referencias a los archivos dentro sin aumentar su recuento de referencias, lo que podría conducir a datos inconsistentes (si se lee / escribe en un inodo cuyos bloques están marcados como libres desde su se eliminó el inodo original), datos perdidos, ya que eliminar la última referencia (conocida) a un archivo podría hacer que se recicle su número de inodo.

Para tl; dr crowd: los
directorios en UNIX son un tipo de archivo, eso es cierto, pero dado que la información dentro de ellos es tratada de manera diferente por el sistema, ya que son metadatos del sistema de archivos, los comandos que manipulan archivos no pueden funcionar en directorios sin un cambio en su comportamiento para manipular los metadatos dependientes también.

Didi Kohen
fuente