¿Cómo se determina el orden en que tar funciona en los archivos?

15
$ touch dir/{{1..8},{a..p}}
$ tar cJvf file.tar.xz dir/
dir/
dir/o
dir/k
dir/b
dir/3
dir/1
dir/i
dir/7
dir/4
dir/e
dir/a
dir/g
dir/2
dir/d
dir/5
dir/8
dir/c
dir/n
dir/f
dir/h
dir/6
dir/l
dir/m
dir/j
dir/p

Hubiera esperado que fuera alfabético. Pero aparentemente no lo es. ¿Cuál es la fórmula aquí?

John
fuente

Respuestas:

14

Como @samiam ha declarado, la lista se le devuelve en un orden semialeatorio a través de readdir(). Solo agregaré lo siguiente.

La lista devuelta es lo que llamaría el orden del directorio. En sistemas de archivos más antiguos, el orden suele ser el orden de creación en el que se agregaron las entradas de archivo en la tabla del directorio. Por supuesto, existe una advertencia al respecto, cuando se elimina una entrada de directorio, esta entrada se recicla, por lo que cualquier archivo posterior que se almacene reemplazará a la entrada anterior, por lo que el pedido ya no se basará únicamente en el tiempo de creación.

En los sistemas de archivos modernos donde las estructuras de datos de directorio se basan en un árbol de búsqueda o una tabla hash, el orden es prácticamente impredecible.

Ejemplos

Al hurgar en los archivos creados cuando ejecuta su comando táctil, se revelan los siguientes inodes asignados.

$ touch dir/{{1..8},{a..p}}
$ stat --printf="%n -- %i\n" dir/*
dir/1 -- 10883235
dir/2 -- 10883236
dir/3 -- 10883242
dir/4 -- 10883243
dir/5 -- 10883244
dir/6 -- 10883245
dir/7 -- 10883246
dir/8 -- 10883247
dir/a -- 10883248
dir/b -- 10883249
dir/c -- 10883250
dir/d -- 10883251
dir/e -- 10883252
dir/f -- 10883253
dir/g -- 10883254
dir/h -- 10883255
dir/i -- 10883256
dir/j -- 10883299
dir/k -- 10883302
dir/l -- 10883303
dir/m -- 10883311
dir/n -- 10883424
dir/o -- 10883426
dir/p -- 10883427

Por lo tanto, podemos ver que la expansión de llaves utilizada por el tacto crea los nombres de los archivos en orden alfabético y, por lo tanto, se les asignan números de inodo secuenciales cuando se escriben en el HDD. (Sin embargo, eso no influye en el orden en el directorio).

Ejecutar su tarcomando varias veces parece indicar que hay un orden en la lista, ya que ejecutarlo varias veces produce la misma lista cada vez. Aquí lo ejecuté 100 veces y luego comparé las ejecuciones y todas son idénticas.

$ for i in {1..100};do tar cJvf file.tar.xz dir/ > run${i};done
$ for i in {1..100};do cmp run1 run${i};done
$ 

Si eliminamos estratégicamente say dir/ey luego agregamos un nuevo archivo dir/ee, podemos ver que este nuevo archivo ha ocupado el lugar que dir/eocupaba anteriormente en la tabla de entradas de directorios.

$ rm dir/e
$ touch dir/ee

Ahora mantengamos la salida de uno de los forbucles anteriores, solo el primero.

$ mv run1 r1A

Ahora, si volvemos a ejecutar el forciclo que ejecutará el tarcomando 100 veces nuevamente, y compararemos esta segunda ejecución con la anterior:

$ sdiff r1A run1
dir/                                dir/
...
dir/c                               dir/c
dir/f                               dir/f
dir/e                             | dir/ee
dir/o                               dir/o
dir/2                               dir/2
...

Notamos que dir/eeha ocupado dir/esu lugar en la tabla de directorios.

slm
fuente
Wow, esta es realmente una gran respuesta. Dado un directorio, ¿hay alguna manera de que yo vea cuál es el orden en que tar procesará sus subelementos? No estoy realmente seguro de ello, pero ¿cómo te parece lo siguiente? stat --printf='%i\t-- %n\n' * | sort -n | sed 's/.*\t-- //'
John
2
Creo que depende del sistema de archivos. Puedo imaginar un sistema de archivos de tipo btree ordenándolos según el orden del hash del archivo o algo similar (tengo la sensación de que el antiguo ReiserFS los ordena de manera diferente, ya que ese sistema de archivos crea dinámicamente inodos)
samiam
1
@samiam: correcto, esta respuesta afirma que el 'orden de directorio' es 'el orden de creación en el que se agregaron las entradas del archivo en la tabla del directorio' y luego muestra fragmentos del contenido del archivo tar que muestran que esto no es cierto. Muchos sistemas de archivos, incluidos los actuales sistemas de archivos ext * de Linux, usan árboles y / o hashes en sus estructuras de directorio, no simples tablas secuenciales como algunos sistemas de archivos más antiguos.
Michał Politowski
3
@John ls -for ls -Uorfind -maxdepth 1
1
@John la -fbandera proviene del antiguo Unix. Su propósito era ser rápido. Inhabilitó la clasificación, la omisión de archivos de puntos y algunas otras cosas. El -Uindicador es una innovación de GNU que le permite deshabilitar la clasificación sin ningún otro efecto secundario.
8

readdir()básicamente. Cuando tar descubre qué archivos hay en un directorio, solicita directamente al núcleo una lista de archivos a través de opendir()seguido de readdir(). readdir()no devuelve los archivos en ningún orden en particular; la forma en que se ordenan los archivos depende del sistema de archivos utilizado por el kernel de Linux.

Ahí, desafortunadamente, no hay una opción para tarordenar archivos en subdirectorios (agregar uno se deja como un ejercicio para el lector).

samiam
fuente
1
Me preguntaba si los recupera en función del valor de su inodo.
slm
1
@slm La f_op->iteratellamada que glibc readdir()finalmente filtra a través de getdents()se asigna a una implementación específica del sistema de archivos. No puedo ver nada en un nivel superior que reordene los direntretornos de la implementación de fs.
Matt
@slm No, nunca he oído hablar de un sistema de archivos en el que el valor del inodo influya en el orden del directorio.
Gilles 'SO- deja de ser malvado'