Como é determinada a ordem na qual o tar funciona nos arquivos?

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

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

John
fonte

Respostas:

14

Como @samiam afirmou, a lista é retornada a você em uma ordem semi-aleatória 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 em que as entradas de arquivo na tabela do diretório foram adicionadas. Obviamente, existe uma ressalva: quando uma entrada de diretório é excluída, essa entrada é reciclada; portanto, todos os arquivos subsequentes armazenados substituem a entrada anterior; portanto, o pedido não será mais baseado apenas no tempo de criação.

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

Exemplos

Ao cutucar os arquivos criados quando você executa o comando touch, os seguintes inodes 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 braçadeira usada pelo toque cria os nomes dos arquivos em ordem alfabética e, portanto, eles recebem números de inodos seqüenciais quando gravados no HDD. (Isso, no entanto, não influencia a ordem no diretório.)

Executar seu tarcomando várias vezes parece indicar que há um pedido para a lista, uma vez que executá-lo várias vezes produz a mesma lista a cada vez. Aqui eu executei 100 vezes e depois comparei as execuções e são todas 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 say dir/ee depois adicionarmos um novo arquivo dir/ee, podemos ver que esse novo arquivo ocupou o lugar que dir/eocupava anteriormente na tabela de entradas de diretórios.

$ rm dir/e
$ touch dir/ee

Agora vamos manter a saída de um dos forloop acima, apenas o primeiro.

$ mv run1 r1A

Agora, se executarmos novamente o forloop que executará o tarcomando 100 vezes novamente e compararemos a 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
...

Notamos que dir/eetomou dir/e's lugar na tabela de diretórios.

slm
fonte
Uau, esta é realmente uma ótima resposta. Dado um diretório, há alguma maneira de eu ver qual é a ordem em que o tar processará seus subitens? Eu não estou realmente confiante sobre isso, mas como o seguinte parece para você? stat --printf='%i\t-- %n\n' * | sort -n | sed 's/.*\t-- //'
John John
2
Eu acho que é dependente do sistema de arquivos. Eu posso imaginar um tipo de btree sistema de arquivos classificando-as com base na ordem de hash do arquivo ou algo assim (eu tenho um sentido os ReiserFS velhas ordens los de forma diferente, uma vez que este sistema de arquivos cria dinamicamente inodes)
Samiam
1
@samiam - certo, esta resposta afirma que a 'ordem do diretório' é 'a ordem de criação em que as entradas do arquivo na tabela do diretório foram adicionadas' e, em seguida, ela mostra fragmentos do conteúdo do arquivo tar, mostrando que isso não é verdade. Muitos sistemas de arquivos, incluindo os sistemas de arquivos ext * atuais do Linux, usam árvores e / ou hashes em suas estruturas de diretório, e não tabelas sequenciais simples como alguns sistemas de arquivos mais antigos.
Michał Politowski 18/03/2014
3
@John ls -for ls -Uorfind -maxdepth 1
1
@ John a -fbandeira vem do antigo Unix. Seu objetivo era ser rápido. Desabilitou a classificação, o pulo de arquivos de pontos e algumas outras coisas. A -Ubandeira é uma inovação GNU que permite desativar a classificação sem outros efeitos colaterais.
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 que está sendo usado pelo kernel do Linux.

Infelizmente, não existe uma opção para tarclassificar arquivos em subdiretórios (a adição de um é deixada como um exercício para o leitor).

samiam
fonte
1
Eu queria saber se ele os recupera com base no valor do seu inode?
slm
1
@slm A f_op->iteratechamada que a glibc readdir()eventualmente filtra para via getdents()é mapeada para uma implementação específica do sistema de arquivos. Não consigo ver nada em um nível superior que reordene os direntretornos da implementação do fs.
Matt
@ slm Não, nunca ouvi falar de um sistema de arquivos em que o valor do inode influenciaria a ordem dos diretórios.
Gilles 'SO- stop be evil'