$ 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
I would have expected it to be alphabetical. But apparently it’s not. What’s the formula, here?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
As @samiam has stated the list is returned to you in a semi-random order via readdir(). I’ll just add the following.
The list returned is what I would call the directory order. On older filesystems, the order is often the creation order that the file entries in the directory’s table were added. There is of course a caveat to this, when a directory entry is deleted, this entry is then recycled, so any subsequent files that are stored will replace the previous entry, so the order will no longer by based solely on creation time.
On modern filesystems where directory data structures are based on a search tree or hash table, the order is practically unpredictable.
Examples
Poking at the files created when you run your touch command reveals the following inodes were assigned.
$ touch dir/{{1..8},{a..p}}
$ stat --printf="%n -- %in" 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
So we can see that the brace expansion used by touch creates the filenames in alphabetical order and so they’re assigned sequential inode numbers when written to the HDD. (That however does not influence the order in the directory.)
Running your tar command multiple times would seem to indicate that there is an order to the list, since running it multiple times yields the same list each time. Here I’ve run it 100 times and then compared the runs and they’re all identical.
$ 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
$
If we strategically delete say dir/e and then add a new file dir/ee we can see that this new file has taken the place that dir/e occupied prior in the directories entries table.
$ rm dir/e $ touch dir/ee
Now let’s keep the output from one of the for loop above, just the 1st one.
$ mv run1 r1A
Now if we re-run the for loop that will run the tar command 100 times again, and compare this second run with the previous one:
$ 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 ...
We notice that dir/ee has taken dir/e‘s place in the directories table.
Method 2
readdir() basically. When tar finds out what files are in a directory, it directly asks the kernel for a file listing via opendir() followed by readdir(). readdir() does not return the files in any particular order; the way the files are ordered depends on the file system being used by the Linux kernel.
There, alas, isn’t an option for tar to sort files in subdirectories (adding one is left as an exercise for the reader).
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0