What's the difference between du -sh *
and du -sh ./*
?
Note: What interests me is the *
and ./*
parts.
bashfilenamesoptionsshellwildcards
What's the difference between du -sh *
and du -sh ./*
?
Note: What interests me is the *
and ./*
parts.
Best Answer
As you can see, the
-c
file was taken as an option todu
and is not reported (and you see thetotal
line because ofdu -c
). Also, the file calleda\n12\tb
is making us think that there are files calleda
andb
.That's better. At least this time
-c
is not taken as an option.That's even better. The
./
prefix prevents-c
from being taken as an option and the absence of./
beforeb
in the output indicates that there's nob
file in there, but there's a file with a newline character (but see below1 for further digressions on that).It's good practice to use the
./
prefix when possible, and if not and for arbitrary data, you should always use:or:
If
cmd
doesn't support--
to mark the end of options, you should report it as a bug to its author (except when it's by choice and documented like forecho
).There are cases where
./*
solves problems that--
doesn't. For instance:fails if there is a file called
a=b.txt
in the current directory (sets the awk variablea
tob.txt
instead of telling it to process the file).Doesn't have the problem because
./a
is not a valid awk variable name, so./a=b.txt
is not taken as a variable assignment.fails if there a file called
-
in the current directory, as that tellscat
to read from its stdin (-
is special to most text processing utilities and tocd
/pushd
).is OK because
./-
is not special tocat
.Things like:
to count the number of files that contain
foo
are wrong because it assumes file names don't contain newline characters (wc -l
counts the newline characters, those output bygrep
for each file and those in the filenames themselves). You should use instead:(counting the number of
/
characters is more reliable as there can only be one per filename).For recursive
grep
, the equivalent trick is to use:./*
may have some unwanted side effects though.adds two more character per file, so would make you reach the limit of the maximum size of arguments+environment sooner. And sometimes you don't want that
./
to be reported in the output. Like:Would output:
instead of:
Further digressions
1. I feel like I have to expand on that here, following the discussion in comments.
Above, that
./
marking the beginning of each file means we can clearly identify where each filename starts (at./
) and where it ends (at the newline before the next./
or the end of the output).What that means is that the output of
du ./*
, contrary to that ofdu -- *
) can be parsed reliably, albeit not that easily in a script.When the output goes to a terminal though, there are plenty more ways a filename may fool you:
Control characters, escape sequences can affect the way things are displayed. For instance,
\r
moves the cursor to the beginning of the line,\b
moves the cursor back,\e[C
forward (in most terminals)...many characters are invisible on a terminal starting with the most obvious one: the space character.
There are Unicode characters that look just the same as the slash in most fonts
(see how it goes in your browser).
An example:
Lots of
x
's buty
is missing.Some tools like
GNU
ls would replace the non-printable characters with a question mark (note that∕
(U+2215) is printable though) when the output goes to a terminal. GNUdu
does not.There are ways to make them reveal themselves:
See how
∕
turned to???
after we toldls
that our character set was ASCII.$
marks the end of the line, so we can spot the"x"
vs"x "
, all non-printable characters and non-ASCII characters are represented by a backslash sequence (backslash itself would be represented with two backslashes) which means it is unambiguous. That was GNUsed
, it should be the same in all POSIX compliantsed
implementations but note that some oldsed
implementations are not nearly as helpful.(not standard but pretty common, also
cat -A
with some implementations). That one is helpful and uses a different representation but is ambiguous ("^I"
and<TAB>
are displayed the same for instance).That one is standard and unambiguous (and consistent from implementation to implementation) but not as easy to read.
You'll notice that
y
never showed up above. That's a completely unrelated issue withdu -hs *
that has nothing to do with file names but should be noted: becausedu
reports disk usage, it doesn't report other links to a file already listed (not alldu
implementations behave like that though when the hard links are listed on the command line).