Bagaimana urutan tar yang bekerja pada file ditentukan?

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

Saya harapkan itu menjadi abjad. Tapi ternyata tidak. Apa formula di sini?

John
sumber

Jawaban:

14

Seperti @samiam telah menyatakan daftar dikembalikan kepada Anda dalam urutan semi-acak via readdir(). Saya hanya akan menambahkan yang berikut ini.

Daftar yang dikembalikan adalah apa yang saya sebut urutan direktori. Pada sistem file yang lebih lama, urutannya sering kali urutan pembuatan yang entri file dalam tabel direktori ditambahkan. Tentu saja ada peringatan untuk ini, ketika entri direktori dihapus, entri ini kemudian didaur ulang, sehingga setiap file berikutnya yang disimpan akan menggantikan entri sebelumnya, sehingga pesanan tidak akan lagi hanya didasarkan pada waktu pembuatan.

Pada sistem file modern di mana struktur data direktori didasarkan pada pohon pencarian atau tabel hash, urutannya praktis tidak dapat diprediksi.

Contohnya

Menyodok file yang dibuat ketika Anda menjalankan perintah sentuh Anda mengungkapkan inode berikut ditugaskan.

$ 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

Jadi kita dapat melihat bahwa ekspansi brace yang digunakan oleh sentuhan menciptakan nama file dalam urutan abjad dan mereka diberi nomor inode berurutan saat ditulis ke HDD. (Namun itu tidak mempengaruhi urutan dalam direktori.)

Menjalankan tarperintah Anda berkali-kali tampaknya menunjukkan bahwa ada urutan ke daftar, karena menjalankannya berkali-kali menghasilkan daftar yang sama setiap kali. Di sini saya telah menjalankannya 100 kali dan kemudian membandingkan prosesnya dan semuanya identik.

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

Jika kita secara strategis menghapus katakan dir/edan kemudian menambahkan file baru dir/eekita dapat melihat bahwa file baru ini telah mengambil tempat yang dir/ediduduki sebelumnya dalam tabel entri direktori.

$ rm dir/e
$ touch dir/ee

Sekarang mari kita menjaga output dari salah satu forloop di atas, hanya yang pertama.

$ mv run1 r1A

Sekarang jika kita menjalankan kembali forloop yang akan menjalankan tarperintah 100 kali lagi, dan bandingkan run kedua ini dengan yang sebelumnya:

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

Kami perhatikan bahwa dir/eetelah dir/eterjadi di tabel direktori.

slm
sumber
Wow, ini benar-benar jawaban yang bagus. Diberikan direktori, apakah ada cara bagi saya untuk melihat apa urutan tar yang akan memproses sub-itemnya? Saya tidak benar-benar yakin tentang hal itu, tetapi bagaimana hal berikut terlihat bagi Anda? stat --printf='%i\t-- %n\n' * | sort -n | sed 's/.*\t-- //'
John
2
Saya pikir itu tergantung pada filesystem. Saya dapat membayangkan filesystem tipe-btree menyortirnya berdasarkan urutan hash file atau semacamnya (Saya memiliki rasa ReiserFS lama memerintahkan mereka secara berbeda, karena filesystem secara dinamis menciptakan inode)
samiam
1
@samiam - benar, jawaban ini mengklaim bahwa 'urutan direktori' adalah 'urutan pembuatan bahwa entri file dalam tabel direktori ditambahkan' dan kemudian itu sendiri menunjukkan fragmen isi file tar yang menunjukkan bahwa ini tidak benar. Banyak filesystem, termasuk filesystem Linux ext * saat ini, menggunakan pohon dan / atau hash dalam struktur direktori mereka, bukan tabel berurutan sederhana seperti beberapa filesystem lama.
Michał Politowski
3
@John ls -fatau ls -Uataufind -maxdepth 1
1
@John the -fflag berasal dari Unix kuno. Tujuannya adalah untuk menjadi cepat. Ini menonaktifkan penyortiran, melewatkan dotfiles, dan beberapa hal lainnya. The -Ubendera adalah inovasi GNU yang memungkinkan Anda untuk menyortir menonaktifkan tanpa efek samping lainnya.
8

readdir()pada dasarnya Ketika tar mengetahui file apa yang ada di direktori, ia langsung meminta kernel untuk daftar file yang opendir()diikuti oleh readdir(). readdir()tidak mengembalikan file dalam urutan tertentu; cara file dipesan tergantung pada sistem file yang digunakan oleh kernel Linux.

Sayangnya, tidak ada opsi untuk tarmengurutkan file dalam subdirektori (menambahkan satu dibiarkan sebagai latihan untuk pembaca).

samiam
sumber
1
Saya bertanya-tanya apakah itu mengambil mereka berdasarkan nilai inode mereka?
slm
1
@slm f_op->iteratePanggilan yang readdir()akhirnya disaring oleh glibc ke getdents()dipetakan ke implementasi spesifik sistem file. Saya tidak dapat melihat apa pun di tingkat yang lebih tinggi yang menata ulang direntpenerapan fs kembali.
Matt
@slm Tidak, saya belum pernah mendengar tentang sistem file di mana nilai inode akan memengaruhi urutan direktori.
Gilles 'SANGAT berhenti menjadi jahat'