Sí, tienes razón, en el pensamiento de que el movimiento de un solo archivo en el mismo sistema de archivos es realmente implementado como cambiar el nombre de un operativo que la estructura del sistema de archivos se ha cambiado para actualizar el nuevo nombre/ubicación del archivo, pero el contenido del archivo no leído/escrito a la unidad de nuevo.
Cuando el movimiento pasa a través de dos diferentes sistemas de archivos (unidades o particiones), entonces el mv
comandos se elimina en primer lugar el destino (si hay un archivo antiguo ya), copia el contenido del archivo en el destino y, finalmente, se elimina el archivo de origen.
El comportamiento se explica en el manual de mv en macOS:
Como cambiar el nombre de la(2) la llamada no funciona a través de sistemas de archivos, mv utiliza cp(1) y rm(1) para realizar el movimiento. El efecto es equivalente a:
rm -f destination_path && \
cp -pRP source_file destination && \
rm -rf source_file
En lo que respecta a la otra respuesta que compara este comportamiento con el código fuente de FreeBSD - el comando mv en macOS en realidad es un poco diferente que en FreeBSD. En particular, se asegura de que los atributos extendidos de recursos y las horquillas se mueve correctamente y no desaparecen cuando se mueve a través del sistema de archivo de límites.
Usted puede leer el real macOS fuente para mv
.
Verás que es similar en estructura como la versión de FreeBSD, pero contiene varios de Apple mejora específica. Además de la funcionalidad se refiere a la ampliación de los atributos y recursos de las horquillas como se describió anteriormente, también tiene mejoras de rendimiento para su uso con Xsan (sistema de archivos distribuido).
Usted encontrará en el código que primero un cambio de nombre se ha intentado:
if (!rename(from, to)) {
if (vflg)
printf("%s -> %s\n", from, to);
return (0);
}
Si esta rename()
falla, el código comprueba por qué ha fallado. Especialmente esto se comprueba por el número de error EXDEV, lo que significa que el cambio de nombre se habría cruzado de los sistemas de archivo, y por lo tanto no se puede hacer:
if (errno == EXDEV) {
struct statfs sfs;
char path[PATH_MAX];
/* Can't mv(1) a mount point. */
if (realpath(from, path) == NULL) {
warnx("cannot resolve %s: %s", from, path);
return (1);
}
if (!statfs(path, &sfs) && !strcmp(path, sfs.f_mntonname)) {
warnx("cannot rename a mount point");
return (1);
}
} else {
warn("rename %s to %s", from, to);
return (1);
}
Tenga en cuenta que este código se anula el movimiento en caso de que la fuente contiene irresoluble enlaces simbólicos, o si es en realidad un punto de montaje - y también por lo general si la rename()
falla por otros motivos que EXDEV.
Sólo en caso de que rename()
de error con el número de error EXDEV, y no por las razones mencionadas anteriormente, se ejecuta el siguiente código:
/*
* If rename fails because we're trying to cross devices, and
* it's a regular file, do the copy internally; otherwise, use
* cp and rm.
*/
if (lstat(from, &sb)) {
warn("%s", from);
return (1);
}
return (S_ISREG(sb.st_mode) ?
fastcopy(from, to, &sb) : copy(from, to));
Este código se ramifica para hacer el movimiento entre los sistemas de archivos de dos maneras diferentes, dependiendo de si o no la fuente que se mueve es en realidad un archivo normal o es algo más. "Algo más" es normalmente un directorio, un enlace simbólico, un nodo de dispositivo o similar.
En el caso de un archivo regular, se utiliza fastcopy()
que simplemente abre los archivos de origen y destino, read()
s de los datos de la fuente y write()
s hasta el destino. A diferencia de la versión de FreeBSD, fastcopy()
función de los usos fcopyfile()
copiar a través de Acl y atributos extendidos desde el origen al destino.
En el caso de algo que no es un archivo regular, simplemente genera comandos externos para realizar el movimiento: cp
para copiar y rm
para eliminar.