4

We have two directories:

$ ls -l
total 8
drwxr-x--- 2 nimmy nimmy 4096 Nov 15 19:42 jeter
drwxr-x--- 2 nimmy nimmy 4096 Nov 15 19:42 mariano

I create one file in the first folder:

$ dd if=/dev/zero of=jeter/zero_file.1 bs=512000 count=1
1+0 records in
1+0 records out
512000 bytes (512 kB) copied, 0.268523 s, 1.9 MB/s

This is the output of du:

$ du -sh *
504K    jeter
4.0K    mariano

As expected, if I place a hard link of the zero_file. in the other folder du output does not change:

$ ln jeter/zero_file.1 mariano/zero_file.2
$ du -sh *
504K    jeter
4.0K    mariano

However, as far as I'm aware, there is nothing in the filesystem that points to zero_file.1 as the original file. So how does du know to count zero_file.1 but not zero_file.2?

It cannot be a timestamp comparison because all hard links share one inode; they'll have the same timestamp data correct?

4 Answers 4

10

Extending your test to three folders, you can see that only the first time the inode is hit does du count it. If you go into the individual folder and run du, you'll get the full size.

To test:

mkdir alexandru
ln mariano/zero_file.2 alexandru/zero_file.0
du -sh *

You should now see alexandru taking up the 500K+. So without looking at the du code, I'm guessing it stores a list of traversed inodes and doesn't revisit the ones already seen.

3
  • 1
    I see. So it traverses the directories alphabetically and keeps track of seen inodes. At least that's what further testing on my side conclude. Nov 16, 2010 at 2:15
  • 5
    I believe that du only traverses directories alphabetically in the cases above because that is the way that the glob expands the wildcard *. I could be wrong about this, but I don't recommend counting on the order being alphabetical. Nov 16, 2010 at 5:12
  • 2
    @Slartibartfast you are correct, running ls | sort -r | xargs du -hs shows the last folder as being 500 K. So it does track inodes in the order it sees them, whether that's alphabetical or otherwise.
    – roguesys
    Nov 16, 2010 at 5:42
4

If you do

du -sh jeter jeter mariano

Then you get 2 different sizes for jeter.

This seems to be in keeping with the finding above...

... except shouldn't the 1st value be the total and the 2nd value be zero?

1
  • Although weird, that's consistent with Dennis Williamson's first POSIX quote, which states that the inode is only remembered for "files with multiple links", implying that files that have only a single (hard) link will be counted every time the directory is included, while those with multiple links will only be counted the first time. +1 for finding an interesting edge case. Nov 22, 2010 at 7:07
3

Apparently, when fstat(3) sees that the number of hard links is greater than one, it records the inode number for subsequent matching. According to POSIX:

Files with multiple links shall be counted and written for only one entry. The directory entry that is selected in the report is unspecified.

The shell expands the * glob in lexical order, according to POSIX:

If the pattern matches any existing filenames or pathnames, the pattern shall be replaced with those filenames and pathnames, sorted according to the collating sequence in effect in the current locale.

However, when du -sh is done without globbing, the order has to be decided in some way, but it sounds like it must be implementation dependent.

Note that these two commands give different results:

du -sh jeter mariano
du -sh mariano jeter
1
  • 1
    When du -sh is done without globbing, the user (caller) will have decided on the order that they provided the arguments. (e.g., jeter mariano or mariano jeter) When it's done with globbing the order is still not decided by du itself, it's decided by the shell, as per your second quoted POSIX passage. Nov 22, 2010 at 7:04
1

If you want to check whether or not your backup from rsync time machine work, and possibly more important how much backup space you are saving, you should do a ls -cr | xargs du -hs which will feed the directories to du in the correct sequence (reversed time of creation).

1
  • This is not an answer to this question. And ls -c sorts by inode change time, not create time (which is generally not stored).
    – Scott
    Jun 13, 2014 at 15:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.