Como a ordem em que o tar trabalha nos arquivos é determinada?

13
$ 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

Eu esperaria que fosse alfabético. Mas aparentemente não é. Qual é a fórmula aqui?

    
por John 18.03.2014 / 04:44

2 respostas

12

Como @samiam declarou que a lista é retornada para você em um pedido semi-aleatório via readdir() . Vou apenas adicionar o seguinte.

A lista retornada é o que eu chamaria de ordem de diretório. Em sistemas de arquivos mais antigos, a ordem geralmente é a ordem de criação na qual as entradas do arquivo na tabela do diretório foram adicionadas. É claro que há uma ressalva, quando uma entrada de diretório é excluída, essa entrada é reciclada, portanto, qualquer arquivo subseqüente armazenado substituirá a entrada anterior, portanto, o pedido não será mais baseado apenas no tempo de criação.

Em sistemas de arquivos modernos, onde as estruturas de dados de diretório são baseadas em uma árvore de busca ou tabela de hash, a ordem é praticamente imprevisível.

Exemplos

Cutucar os arquivos criados quando você executa o comando touch revela que os inodes a seguir foram atribuídos.

$ 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

Assim, podemos ver que a expansão de chave usada pelo touch cria os nomes dos arquivos em ordem alfabética e, portanto, eles recebem números de inode seqüenciais quando gravados no HDD. (Isso, no entanto, não influencia a ordem no diretório.)

Executar o comando tar várias vezes parece indicar que há uma ordem na lista, já que executá-lo várias vezes gera a mesma lista a cada vez. Aqui eu corri 100 vezes e então comparei as corridas e todas são 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
$ 

Se excluirmos estrategicamente o dir/e e, em seguida, adicionarmos um novo arquivo dir/ee , poderemos ver que esse novo arquivo ocupou o lugar que dir/e ocupou antes na tabela de entradas de diretórios.

$ rm dir/e
$ touch dir/ee

Agora vamos manter a saída de um dos loop for acima, apenas o 1º.

$ mv run1 r1A

Agora, se executarmos novamente o loop for que executará o comando tar 100 vezes novamente e compararemos essa segunda execução com a 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
...

Percebemos que dir/ee ocupou o lugar de dir/e na tabela de diretórios.

    
por 18.03.2014 / 05:48
8

readdir() basicamente. Quando o tar descobre quais arquivos estão em um diretório, ele solicita diretamente ao kernel uma listagem de arquivos via opendir() seguido por readdir() . readdir() não retorna os arquivos em nenhuma ordem específica; A maneira como os arquivos são ordenados depende do sistema de arquivos usado pelo kernel Linux.

Lá, infelizmente, não é uma opção para tar classificar arquivos em subdiretórios (a adição de um é deixada como um exercício para o leitor).

    
por 18.03.2014 / 05:04