Come viene determinato l'ordine in cui tar funziona sui file?


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

Mi sarei aspettato che fosse alfabetico. Ma a quanto pare non lo è. Qual è la formula, qui?

Risposte:


14

Come ha affermato @samiam, l'elenco viene restituito in un ordine semi-casuale tramite readdir(). Aggiungerò solo quanto segue.

L'elenco restituito è ciò che definirei l'ordine delle directory. Sui file system meno recenti, l'ordine è spesso l'ordine di creazione in cui sono state aggiunte le voci del file nella tabella della directory. Ovviamente c'è un avvertimento a questo, quando una voce della directory viene eliminata, questa voce viene quindi riciclata, quindi tutti i file successivi che vengono memorizzati sostituiranno la voce precedente, quindi l'ordine non sarà più basato esclusivamente sul tempo di creazione.

Sui moderni filesystem in cui le strutture di dati di directory sono basate su un albero di ricerca o una tabella hash, l'ordine è praticamente imprevedibile.

Esempi

Frugando sui file creati quando si esegue il comando touch, vengono rivelati i seguenti inode.

$ 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

Quindi possiamo vedere che l'espansione del controvento usata dal tocco crea i nomi dei file in ordine alfabetico e quindi sono assegnati numeri di inode sequenziali quando sono scritti sull'HDD. (Ciò tuttavia non influenza l'ordine nella directory.)

L'esecuzione del tarcomando più volte sembra indicare che esiste un ordine nell'elenco, poiché l'esecuzione più volte produce lo stesso elenco ogni volta. Qui l'ho eseguito 100 volte e poi ho confrontato le piste e sono tutte identiche.

$ 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 eliminiamo strategicamente say dir/ee quindi aggiungiamo un nuovo file dir/ee, possiamo vedere che questo nuovo file ha preso il posto che dir/eoccupava prima nella tabella delle voci delle directory.

$ rm dir/e
$ touch dir/ee

Ora manteniamo l'output di uno dei forloop sopra, solo il primo.

$ mv run1 r1A

Ora, se eseguiamo nuovamente il forciclo che eseguirà tarnuovamente il comando 100 volte e confronteremo questa seconda esecuzione con la precedente:

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

Notiamo che dir/eeha preso dir/eposto nella tabella delle directory.


Caspita, questa è davvero un'ottima risposta. Data una directory, c'è un modo per me di vedere in quale ordine sarà tar i suoi sotto-elementi? Non ne sono davvero sicuro, ma come ti sembra il seguente? stat --printf='%i\t-- %n\n' * | sort -n | sed 's/.*\t-- //'
Giovanni

2
Penso che dipenda dal filesystem. Posso immaginare un filesystem di tipo btree che li ordina in base all'ordine dell'hash dei file o alcuni di questi (ho la sensazione che il vecchio ReiserFS li ordini in modo diverso, dal momento che quel filesystem crea dinamicamente inode)
samiam

1
@samiam - giusto, questa risposta afferma che l '"ordine di directory" è "l'ordine di creazione in cui sono state aggiunte le voci del file nella tabella della directory" e quindi esso stesso mostra frammenti del contenuto del file tar dimostrando che ciò non è vero. Molti filesystem, inclusi gli attuali filesystem ext Linux, usano alberi e / o hash nelle loro strutture di directory, non semplici tabelle sequenziali come alcuni vecchi filesystem.
Michał Politowski,

3
@John ls -foppure ls -Uoppurefind -maxdepth 1

1
@Giovanni la -fbandiera viene dall'antica Unix. Il suo scopo era quello di essere veloce. Ha disabilitato l'ordinamento, il salto di dotfile e poche altre cose. La -Ubandiera è un'innovazione GNU che ti consente di disabilitare l'ordinamento senza altri effetti collaterali.

8

readdir()fondamentalmente. Quando tar scopre quali file si trovano in una directory, chiede direttamente al kernel un elenco di file opendir()seguito da readdir(). readdir()non restituisce i file in alcun ordine particolare; il modo in cui i file vengono ordinati dipende dal file system utilizzato dal kernel Linux.

Lì, purtroppo, non è un'opzione per tarordinare i file nelle sottodirectory (aggiungerne uno viene lasciato come esercizio per il lettore).


1
Mi chiedevo se li recupera in base al valore del loro inode?
slm

1
@slm La f_op->iteratechiamata che glibc readdir()alla fine filtra verso il basso getdents()viene mappata su un'implementazione specifica del filesystem. Non riesco a vedere nulla a un livello superiore che riordini i direntritorni dell'implementazione di fs.
Matt

@slm No, non ho mai sentito parlare di un filesystem in cui il valore dell'inode influirebbe sull'ordine delle directory.
Gilles 'SO-smetti di essere malvagio' il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.