Làm thế nào để thứ tự tar hoạt động trên các tập tin được xác định?


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

Tôi đã mong đợi nó được theo thứ tự abc. Nhưng dường như không phải vậy. Công thức ở đây là gì?

Câu trả lời:


14

Như @samiam đã tuyên bố danh sách được trả lại cho bạn theo thứ tự bán ngẫu nhiên thông qua readdir(). Tôi sẽ chỉ thêm vào như sau.

Danh sách trả về là những gì tôi sẽ gọi thứ tự thư mục. Trên các hệ thống tệp cũ hơn, thứ tự thường là thứ tự tạo mà các mục nhập tệp trong bảng của thư mục đã được thêm vào. Tất nhiên có một sự cảnh báo cho điều này, khi một mục nhập thư mục bị xóa, mục nhập này sau đó được tái chế, do đó, bất kỳ tệp nào được lưu trữ sẽ thay thế mục nhập trước đó, vì vậy đơn hàng sẽ không còn chỉ dựa vào thời gian tạo.

Trên các hệ thống tệp hiện đại nơi cấu trúc dữ liệu thư mục dựa trên cây tìm kiếm hoặc bảng băm, thứ tự thực tế không thể đoán trước.

Ví dụ

Chọc vào các tệp được tạo khi bạn chạy lệnh cảm ứng cho thấy các nút sau được chỉ định.

$ 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

Vì vậy, chúng ta có thể thấy rằng việc mở rộng dấu ngoặc được sử dụng bởi cảm ứng tạo ra tên tệp theo thứ tự bảng chữ cái và do đó chúng được gán các số inode liên tiếp khi được ghi vào ổ cứng. (Tuy nhiên, điều đó không ảnh hưởng đến thứ tự trong thư mục.)

Chạy tarlệnh của bạn nhiều lần dường như cho thấy rằng có một thứ tự cho danh sách, vì chạy nó nhiều lần sẽ mang lại cùng một danh sách mỗi lần. Ở đây tôi đã chạy nó 100 lần và sau đó so sánh các lần chạy và chúng đều giống hệt nhau.

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

Nếu chúng ta xóa chiến lược nói dir/evà sau đó thêm một tệp mới, dir/eechúng ta có thể thấy rằng tệp mới này đã chiếm vị trí dir/echiếm chỗ trước trong bảng mục nhập thư mục.

$ rm dir/e
$ touch dir/ee

Bây giờ, hãy giữ đầu ra từ một trong các forvòng lặp ở trên, chỉ là vòng đầu tiên.

$ mv run1 r1A

Bây giờ nếu chúng ta chạy lại forvòng lặp sẽ chạy lại tarlệnh 100 lần và so sánh lần chạy thứ hai này với vòng lặp trước:

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

Chúng tôi nhận thấy rằng dir/eeđã thực hiệndir/e vị trí trong bảng thư mục.


Wow, đây thực sự là một câu trả lời tuyệt vời. Đưa ra một thư mục, có cách nào để tôi xem thứ tự mà tar sẽ xử lý các mục con của nó là gì không? Tôi không thực sự tự tin về điều đó, nhưng những điều sau đây đối với bạn như thế nào? stat --printf='%i\t-- %n\n' * | sort -n | sed 's/.*\t-- //'
John

2
Tôi nghĩ đó là hệ thống tập tin phụ thuộc. Tôi có thể tưởng tượng một hệ thống tệp loại btree sắp xếp chúng dựa trên thứ tự băm tệp hoặc một số thứ khác (tôi có cảm giác ReiserFS cũ sắp xếp chúng theo cách khác, vì hệ thống tệp đó tự động tạo ra các
nút

1
@samiam - đúng, câu trả lời này tuyên bố rằng 'thứ tự thư mục' là 'thứ tự tạo mà các mục trong tệp của thư mục đã được thêm vào' và sau đó chính nó hiển thị các đoạn của nội dung tệp tar cho thấy điều này không đúng. Nhiều hệ thống tệp, bao gồm các hệ thống tệp ext * hiện tại của Linux, sử dụng cây và / hoặc băm trong cấu trúc thư mục của chúng, chứ không phải các bảng tuần tự đơn giản như một số hệ thống tệp cũ hơn.
Michał Politowski

3
@ John ls -fhoặc ls -Uhoặcfind -maxdepth 1

1
@ John -fcờ đến từ Unix cổ đại. Mục đích của nó là nhanh Nó vô hiệu hóa việc sắp xếp, bỏ qua các dotfiles và một vài thứ khác. Các -Ulá cờ là một sự đổi mới GNU cho phép bạn vô hiệu hóa phân loại mà không cần bất kỳ tác dụng phụ khác.

8

readdir()về cơ bản. Khi tar tìm ra tập tin nào trong một thư mục, nó sẽ hỏi trực tiếp kernel để liệt kê tập tin quaopendir() tiếp theo readdir(). readdir()không trả lại các tập tin theo bất kỳ thứ tự cụ thể nào; cách các tệp được sắp xếp tùy thuộc vào hệ thống tệp được sử dụng bởi nhân Linux.

Ở đó, than ôi, không phải là một tùy chọn tarđể sắp xếp các tệp trong thư mục con (thêm một cái còn lại như một bài tập cho người đọc).


1
Tôi đã tự hỏi nếu nó lấy chúng dựa trên giá trị inode của chúng?
slm

1
@slm Cuộc f_op->iterategọi mà readdir()cuối cùng glibc lọc xuống thông qua getdents()được ánh xạ tới một triển khai cụ thể của hệ thống tệp. Tôi không thể thấy bất cứ điều gì ở cấp độ cao hơn sắp xếp lại việc direntthực hiện fs.
Matt

@slm Không, tôi chưa bao giờ nghe nói về một hệ thống tập tin trong đó giá trị inode sẽ có ảnh hưởng đến thứ tự thư mục.
Gilles 'SO- đừng trở nên xấu xa'
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.