7 votos

¿Cómo funciona el comando mv con unidades externas?

En el mismo disco, asumo que cambiaría algo así como una tabla FAT para volver a ubicar la ubicación de los archivos.

Pregunta

Cuando se va a una unidad diferente (tal vez incluso a una partición), ¿el comando mv copia primero, luego se eliminan los archivos antiguos, para evitar la pérdida de datos si se produce una excepción?

10voto

ParanoidGeek Puntos 41

El mv de macOS se basa en el código fuente de BSD. Puede encontrar el código fuente del comando mv en línea. Utilizando https://github.com/freebsd/freebsd/blob/master/bin/mv/mv.c como referencia, puede ver que efectivamente intentan cambiar el nombre del archivo y luego, si está cruzando los sistemas de archivos, hace un cp seguido de un rm .

     /*
     * 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));
}
 

6voto

Jose Chavez Puntos 645

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.

AppleAyuda.com

AppleAyuda es una comunidad de usuarios de los productos de Apple en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X