ลำดับของ tar ที่ทำงานกับไฟล์ถูกกำหนดอย่างไร


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

ฉันคาดว่าจะเป็นตัวอักษร แต่เห็นได้ชัดว่าไม่ใช่ นี่สูตรอะไร

คำตอบ:


14

ในฐานะที่เป็น@samiamreaddir()ได้ระบุไว้ในรายการจะถูกส่งกลับให้กับคุณในการสั่งซื้อกึ่งสุ่มผ่าน ฉันจะเพิ่มต่อไปนี้

รายการที่ส่งคืนคือสิ่งที่ฉันจะเรียกลำดับไดเรกทอรี บนระบบไฟล์ที่เก่ากว่าลำดับมักจะเป็นลำดับการสร้างที่เพิ่มรายการไฟล์ในตารางของไดเรกทอรี แน่นอนมีข้อแม้นี้เมื่อลบรายการไดเรกทอรีรายการนี้จะถูกรีไซเคิลแล้วดังนั้นไฟล์ใด ๆ ที่ตามมาที่เก็บไว้จะแทนที่รายการก่อนหน้าดังนั้นคำสั่งจะไม่ขึ้นอยู่กับเวลาในการสร้างเพียงอย่างเดียว

บนระบบไฟล์ที่ทันสมัยซึ่งโครงสร้างข้อมูลไดเรกทอรีขึ้นอยู่กับโครงสร้างการค้นหาหรือตารางแฮชลำดับที่ไม่สามารถคาดเดาได้จริง

ตัวอย่าง

poking ที่ไฟล์ที่สร้างขึ้นเมื่อคุณเรียกใช้คำสั่ง touch ของคุณเผยให้เห็น inodes ต่อไปนี้ได้รับมอบหมาย

$ 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

ดังนั้นเราจะเห็นได้ว่าการขยายตัวรั้งที่ใช้โดยการสัมผัสสร้างชื่อไฟล์ตามลำดับตัวอักษรดังนั้นพวกเขาจึงได้รับหมายเลขไอโหนดเรียงตามลำดับเมื่อเขียนไปยัง HDD (อย่างไรก็ตามจะไม่มีผลกับลำดับในไดเรกทอรี)

การรันtarคำสั่งของคุณหลายครั้งดูเหมือนจะบ่งบอกว่ามีคำสั่งไปยังรายการเนื่องจากการรันคำสั่งหลายครั้งจะทำให้รายการเดียวกันทุกครั้ง ที่นี่ฉันวิ่ง 100 ครั้งแล้วเปรียบเทียบการวิ่งและมันเหมือนกันหมด

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

ถ้าเราลบพูดอย่างมีกลยุทธ์ dir/eแล้วเพิ่มไฟล์ใหม่dir/eeเราจะเห็นว่าไฟล์ใหม่นี้เกิดขึ้นdir/eก่อนหน้านี้ในตารางรายการไดเรกทอรี

$ rm dir/e
$ touch dir/ee

ทีนี้ลองเอาท์พุทจากหนึ่งในforลูปข้างบน, แค่อันที่ 1

$ mv run1 r1A

ตอนนี้ถ้าเราเรียกใช้อีกครั้ง forวนซ้ำที่จะรันtarคำสั่ง 100 ครั้งอีกครั้งและเปรียบเทียบการวิ่งครั้งที่สองกับอันก่อนหน้านี้:

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

เราสังเกตเห็นว่าdir/eeเกิดdir/eขึ้นในตารางไดเรกทอรี


ว้าวนี่เป็นคำตอบที่ดีจริงๆ ให้ไดเรกทอรีมีวิธีใดบ้างที่ฉันจะเห็นลำดับที่ tar จะประมวลผลรายการย่อยในนั้นคืออะไร? ฉันไม่มั่นใจจริง ๆ แต่สิ่งต่อไปนี้มีลักษณะอย่างไรกับคุณ stat --printf='%i\t-- %n\n' * | sort -n | sed 's/.*\t-- //'
John

2
ฉันคิดว่ามันขึ้นอยู่กับระบบไฟล์ ฉันสามารถจินตนาการระบบไฟล์ประเภท btree ที่เรียงลำดับตามแฮชของไฟล์หรือบางอย่าง (ฉันมีความรู้สึกว่า ReiserFS เก่าสั่งให้พวกเขาแตกต่างกันเนื่องจากระบบไฟล์นั้นสร้าง inodes แบบไดนามิก)
samiam

1
@samiam - คำตอบนี้อ้างว่า 'ลำดับของไดเรกทอรี' คือ 'ลำดับการสร้างที่เพิ่มรายการไฟล์ในตารางของไดเรกทอรี' และจากนั้นจะแสดงชิ้นส่วนของเนื้อหาไฟล์ tar ที่แสดงว่าไม่เป็นความจริง ระบบไฟล์จำนวนมากรวมถึงระบบไฟล์ Linux ext * ปัจจุบันใช้แผนผังและ / หรือแฮชในโครงสร้างไดเรกทอรีไม่ใช่ตารางเรียงลำดับอย่างง่ายเช่นระบบไฟล์เก่าบางระบบ
Michał Politowski

3
@ John ls -fหรือls -Uหรือfind -maxdepth 1

1
@John -fธงมาจาก Unix โบราณ จุดประสงค์คือต้องรวดเร็ว มันปิดใช้งานการเรียงลำดับการข้าม dotfiles และสิ่งอื่น ๆ การ-Uตั้งค่าสถานะเป็นนวัตกรรมของ GNU ที่ให้คุณปิดการเรียงลำดับโดยไม่มีผลข้างเคียงอื่น ๆ

8

readdir()เป็นพื้น เมื่อ tar พบไฟล์ที่อยู่ในไดเรกทอรีมันจะถามเคอร์เนลโดยตรงเพื่อหารายชื่อไฟล์opendir()ตามด้วยreaddir()ตามด้วย readdir()ไม่ส่งคืนไฟล์ตามลำดับใด ๆ วิธีการจัดเรียงไฟล์จะขึ้นอยู่กับระบบไฟล์ที่ใช้โดยเคอร์เนล Linux

อนิจจาไม่ใช่ตัวเลือกสำหรับtarเรียงลำดับไฟล์ในไดเรกทอรีย่อย (เพิ่มอีกหนึ่งไฟล์ที่เหลือเป็นแบบฝึกหัดสำหรับผู้อ่าน)


1
ฉันสงสัยว่ามันจะดึงพวกมันตามค่า inode หรือเปล่า?
slm

1
@slm การf_op->iterateเรียกที่ glibc readdir()ในที่สุดกรองลงผ่านgetdents()จะถูกแมปกับการใช้งานเฉพาะของระบบไฟล์ ฉันไม่เห็นอะไรเลยในระดับที่สูงขึ้นซึ่งจะเรียงลำดับdirentผลการดำเนินงานของ fs กลับคืนมา
Matt

@slm ไม่ฉันไม่เคยได้ยินเกี่ยวกับระบบไฟล์ที่ค่า inode จะมีผลกับลำดับไดเรกทอรี
Gilles 'หยุดความชั่วร้าย'
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.