Entiendo muy bien la noción de enlaces duros, y he leído las páginas del manual sobre herramientas básicas como cp
--- e incluso las especificaciones POSIX recientes --- varias veces. Aún así me sorprendió observar el siguiente comportamiento:
$ echo john > john
$ cp -l john paul
$ echo george > george
En este punto john
y paul
tendrá el mismo inodo (y contenido), y george
diferirá en ambos aspectos. Ahora hacemos:
$ cp george paul
En este punto esperaba george
y paul
tener diferentes números de inodo pero el mismo contenido --- esta expectativa se cumplió --- pero también esperaba paul
tener ahora un número de inodo diferente de john
, y john
aún tener el contenido john
. Aquí es donde me sorprendió. Resulta que copiar un archivo a la ruta de destino paul
también tiene el resultado de instalar ese mismo archivo (mismo inodo) en todas las demás rutas de destino que comparten paul
el inodo. Estaba pensando que cp
crea un nuevo archivo y lo mueve al lugar anteriormente ocupado por el archivo anterior paul
. En cambio, lo que parece hacer es abrir el archivo existente paul
, truncarlo y escribirgeorge
El contenido de ese archivo existente. Por lo tanto, cualquier "otro" archivo con el mismo inodo actualiza "su" contenido al mismo tiempo.
Ok, este es un comportamiento sistemático y ahora que sé que puedo esperarlo, puedo descubrir cómo solucionarlo o aprovecharlo, según corresponda. Lo que me desconcierta es dónde se suponía que debía ver este comportamiento documentado. Me sorprendería si no está documentado en algún lugar de los documentos que ya he visto. Pero aparentemente me lo perdí, y ahora no puedo encontrar una fuente que discuta este comportamiento.
cp
documentos que sobrescribe el archivo de destino si el archivo de destino ya está presente. Tiene razón en que no especifica en detalle qué significa "sobrescribir", pero definitivamente dice "sobrescribir", no "reemplazar". Si quiere ser pedante, puede argumentar que "sobrescribir" es exactamente lo quecp
hace, y el comportamiento que esperaba se llamaría correctamente "reemplazar".También tenga en cuenta que si
cp
"reemplazara" archivos de destino preexistentes, eso podría considerarse razonablemente sorprendente o incorrecto, probablemente más que "sobrescribir". Por ejemplo:cp
primero eliminó el archivo antiguo y luego creó uno nuevo, habría un intervalo de tiempo durante el cual el archivo estaría ausente, lo que sería sorprendente.cp
primero creó un archivo temporal y luego lo movió en su lugar, entonces probablemente debería documentarlo, debido al hecho de que ocasionalmente se notarían tales archivos temporales con nombres extraños ... pero no lo hace.cp
no puede crear un nuevo archivo en el mismo directorio que el anterior debido a los permisos, sería desafortunado (especialmente si ya hubiera eliminado el anterior).cp
y el usuario en ejecucióncp
no eraroot
, sería imposible hacer coincidir el propietario y los permisos del nuevo archivo con los del nuevo archivo.cp
no conoce, entonces estos se perderían en la copia. Hoy en día, las implementaciones decp
deberían comprender de manera confiable cosas como los atributos extendidos, pero no siempre fue así. Y hay otras cosas, como los tenedores de recursos de MacOS o, para sistemas de archivos remotos, básicamente cualquier cosa.En conclusión: ahora sabes lo que
cp
realmente hace. ¡Nunca más te sorprenderá! Honestamente, creo que lo mismo me podría haber pasado a mí también, hace muchos años.fuente
man
páginas decp
BSD (al menos, OSX) y las versiones de Gnucp
no son tan explícitas sobre la "sobrescritura". Esa palabra solo se usa en los comentarios sobre opciones-i
y-n
. La página de manual de Gnu es especialmente poco informativa, comenzandoCopy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.
La página deIn the first synopsis form, the cp utility copies the contents of the source_file to the target_file.
‘cp’ copies files (or, optionally, directories). The copy is completely independent of the original.
Veo que el estándar POSIX 2013 sí especifica el comportamiento observado . Dice:
fuente
cp
que daría resultados similaresmv
y rompería los enlaces duros de los que formaba parte el destino. Pero ahora que lo pienso, eso significaría que tendría que ser específicamenteunlink(2)
el objetivo (cp -f
), o crear un temporal con un nombre diferente y luegorename(2)
. La implementación sencilla es simplemente abrir el archivo para sobrescribir, que es lo que requiere POSIX. Es equivalente acat src > dest
Si puede decir, "copiar un archivo a la ruta de destino
paul
también copia el mismo archivo (mismo inodo) a todas las otras rutas de destino que compartenpaul
el inodo", lamento decir que no comprende la noción de enlaces duros muy bien. Si le doy una manzana a Sir McCartney, le he dado una manzana a Paul, y le he dado una manzana al compañero de composición de John Lennon. Pero no he dado tres manzanas; Le he dado una manzana a una persona que tiene múltiples nombres / títulos / descriptores.Del mismo modo, cuando se copia
george
apaul
, usted no está también copia ajohn
. Por el contrario, está copiando losgeorge
datos en el archivo cuyo inodo señala lapaul
entrada del directorio.Paso a paso: cuando lo haces
ha creado un nuevo archivo (suponiendo que no haya un archivo nombrado
john
en ese directorio). O, para hablar más estrictamente, esto supone que no había una entrada de directorio con el nombrejohn
en ese directorio (porque, estrictamente hablando, no hay archivos en los directorios; solo entradas de directorio, que apuntan a inodes). Después de que lo hagaso
no ha creado un nuevo archivo; más bien, le ha dado un nombre nuevo a su archivo existente. Ahora tiene un archivo con dos nombres:
john
ypaul
. Y cuando dicesEstás sobrescribiendo ese archivo . El hecho de que tenga dos nombres es irrelevante; podría tener 42 nombres, posiblemente en lugares a los que ni siquiera puede acceder, y este comando no estaría copiando los
george\n
datos a todos esos nombres (rutas); solo está copiando los datos en un archivo que tiene varios nombres.fuente
john
y comencépaul
como dos nombres de ruta para el mismo archivo. Pero era la forma más fácil en que podía pensar para expresarme. No creo que la mera noción de un enlace duro, entendido correctamente, dicte cualquiera de los dos comportamientos paracp
(sin-l
).