¿Por qué el programa unix mv no necesita la opción -R (recursiva) para directorios pero cp sí la necesita?


58

Siempre me equivoco cuando necesito usar cpo mv: "¿Necesito una -Ropción cuando trabajo con dir?" En GNU coreutils cpnecesita -Ry mvno necesita .

Simplemente no puedo encontrar ninguna razón por la que cpnecesita una -Ropción para copiar directorios y mvno lo hace. Creo que cping dirs sin -R(pero comportarse recursivamente como hay -Ry como mvhace) no causaría ningún problema, excepto romper los hábitos de alguien al usar la herramienta.

¿Conoces alguna explicación? Puede ser que tuviera una razón hace mucho tiempo?


Pregunta adicional: ¿por qué los desarrolladores de coreutils no hacen directorios de cpcopia de forma recursiva por defecto?

Respuestas:


45

Un directorio es (conceptualmente) un "archivo" especial que contiene una lista de nombres y los números de inodo a los que apuntan esos nombres. Algunos nombres pueden ser subdirectorios. Hay una entrada especial ..que apunta al directorio padre.

Entonces, está claro, cambiar el nombre de un archivo es fácil: solo cambia el nombre en la entrada del directorio, nada más. Esto sostiene si el archivo es realmente un archivo o es un "archivo" utilizado para almacenar el contenido de otro directorio. De hecho, la misma renamellamada al sistema hace ambas cosas.

Copiar, sin embargo, es una operación mucho menos trivial. Usted podría simplemente copiar el "archivo" directorio, pero entonces tendría dos directorios donde se encuentran los archivos son los mismos (que serían los enlaces duros). Si tuviera un sistema que permita enlaces duros a directorios, sería, pero dado que ningún sistema moderno lo permite, al menos a los no root, debe hacer esa copia para cada subdirectorio. En realidad, puede solicitar cpeste comportamiento con cp -lR: -lpara el enlace duro, -Rpara esa recursión.

Pero dejar todo vinculado probablemente no sea lo que quieres. En su lugar, desea cpcopiar cada archivo. Esa es una operación bastante costosa: cada archivo debe leerse en la memoria y escribirse nuevamente en el disco en una segunda ubicación. En realidad, se requieren varias llamadas al sistema para abrir, leer, escribir y cerrar los archivos, y eso tiene que repetirse para cada archivo.

Los sistemas de archivos tradicionales también funcionan de esta manera en el disco. No hay ninguna forma de copiar un montón de archivos, aparte de revisar cada uno individualmente y copiarlo, y esos son los tipos de sistemas de archivos que estaban en uso cuando se diseñaron las utilidades básicas de la línea de comandos.


¿Está mvpasando de un sistema de archivos a otro el mismo "solo cambia el nombre en la entrada del directorio"?
rslnx

55
No, el sistema de archivos cruzados es lo mismo que copiar + eliminar (de hecho, la renamesyscall fallará para el sistema de archivos cruzados). No estoy seguro si, históricamente, mvincluso apoyó movimientos cruzados.
derobert

99
Puedo decirles, por experiencia directa, no por especulación, que los clásicos mvno admitían movimientos entre dispositivos. Solía ​​probar rename()e imprimir un mensaje de error si fallaba. Todavía recuerdo la sensación de asombro que tuve la primera vez que usé accidentalmente la nueva función. ¿Por qué está tardando tanto este MV? ¡Oh, está haciendo una copia recursiva que no tenía la intención!
Alan Curry

55
Las opciones de línea de comandos de @RuslanKhusnullin a comandos comunes son muy difíciles de cambiar, debido a su uso en scripts de shell. Alguien puede depender del comportamiento actual de rechazar copiar archivos de cp. Probablemente se consideró que el material de cross-fs era menos probable que causara rotura, aunque, como puede ver, todavía sorprendió a Alan.
derobert

1
@derobert, no lo hizo (el sistema de archivos cruzados mvfuncionó solo para archivos individuales en BSD 4.2 en VAX).
vonbrand

21

Permítanme comenzar haciendo otra pregunta:

¿Cuál es la diferencia entre cpy cp -R?

Bueno, sin la -Rbandera, solo es posible copiar archivos, porque es bastante inusual que alguien quiera copiar un directorio de forma no recursiva: una copia no recursiva solo daría como resultado un segundo nombre para el directorio, apuntando directamente al mismo directorio estructura. Debido a que rara vez eso es lo que la gente quiere, y en realidad hay un programa separado que hace esto ( ln), no se permite una copia no recursiva de directorios.

¿Cuál podría ser la diferencia entre mvy mv -R?

mv a bsolo cambia el nombre de una sola entrada en el directorio, por lo que si se mvedita un directorio , su contenido también se mueve automáticamente. En ese sentido, mvya proporciona la propiedad recursiva, es decir, el "cambio de nombre" de todas las entradas en el directorio renombrado, por ejemplo, de a/1a b/1. A mvque no hace eso, es decir, que cambia el nombre de un directorio aa b, pero mantiene a/1como a/1, no es lo que la gente entiende cuando se refieren a mover algo: Al mover un armario, el contenido del armario se mueven también. Esa otra operación, mover un directorio sin su contenido, también ya está disponible, se llama mkdir.


2
Así es, solo estaba pensando cpy mvcomo operaciones que se llaman: 'hacer una copia' y 'mover'. Entonces, si quiero hacer una copia de una taza de café, esperaría tomar otra taza de café con el mismo relleno (bebida de café). El problema es que las herramientas no están destinadas a 'personas habituales' sino a nerds que conocen la estructura del sistema de archivos y discos, no entidades virtuales como archivos y directorios de archivos.
rslnx

1
Respuesta bien estructurada y razonada.
Spedge

1
@RuslanKhusnullin Su analogía con el café también funciona cpy mvno requiere ningún nivel de "nerdness" para entender, solo sentido común básico. Una copia verdadera de una taza de café no es una taza vacía: debe copiar recursivamente no solo la taza, sino también todo su contenido (el café). Sin embargo, cuando mueve una taza de café, no tiene que mover el contenido por separado; el contenido se mueve con el recipiente de forma natural.
jw013

1
@ jw013 Me ha impresionado con "cuando mueve una taza de café no tiene que mover el contenido por separado", realmente tiene sentido, gracias. Pero es otra capa de abstracción. Creo que te refieres a "tratar un archivo como un inodo" mientras pienso en archivos como secuencias de bytes sin metainformación.
rslnx

6

Por lo general, cuando me equivoco con la lógica de Unix, miro Plan9 para ver cómo los inventores de Unix implementaron las mismas tareas años después sin atascarse en la compatibilidad con versiones anteriores.

Entonces Plan9 ofrece cpy mvherramientas para operar solo con archivos.

`cp f1 f2` creates f2 and copies f1's contents into it.
`mv f1 f2` renames f1 to f2 if f1 and f2 are in the same dir
           does `cp f1 f2 && rm f1` else
           can rename dirs (`mv d1 d2`) but will not move dir to another dir.

Para copiar un directorio hay dircpque es realmente @{cd fromdir && tar c .} | @{cd todir && tar xT}(sintaxis de shell rc)

Para mover un directorio creo que solo hay dircp d1 d2 && rm -r d1

Creo que esta decisión de limitar cpy solo mvpara operaciones de archivo (no dirs) aporta más claridad a las operaciones de disco y el uso tarpara copiar árboles de archivos es muy cómodo para comprender y crear secuencias de comandos.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.