One is correct, the other isn’t.
du -sh *
(should be du -sh -- *
to avoid problems with filenames starting with -
)
relies on the shell to expand the glob *
; du
sees all the non-hidden files and directories in the current directory as individual arguments. This handles special characters correctly.
ls | xargs du -sh
relies on xargs
to process ls
’s output. xargs
splits its input on whitespace (at least space, tab and newline, more with some implementations), also understanding some form of quoting, and runs du
(one (even for an empty input¹) or more invocations) with every single whitespace-separated string as individual arguments.
Both appear equivalent if your current directory doesn’t contain files with whitespace, single quote, double quote or backslash characters in their names, and if there are few enough files (but at least one) that xargs
runs only one du
invocation, but they’re not.
In terms of efficiency, du -sh *
uses one process, ls | xargs du -sh
uses at least three. There is one scenario where the pipe approach will work, while the glob won’t: if you have too many files in the current directory, the shell won’t be able to run du
with all their names in one go, but xargs
will run du
as many times as necessary to cover all the files, in which case you would see several lines, and files with more than one hard link may be counted several times.
See also Why *not* parse `ls`?
¹ If there's no non-hidden file in the current directory du -sh -- *
will either fail with an error by your shell, or with some shells like bash
run du
with a literal *
as argument and du
will complain about that *
file not existing.
While with ls | xargs du -sh --
, most xargs
implementations (exceptions being some BSD) will run du
with no argument and so give the disk usage of the current directory (so also including the disk usage of the directory file itself and all hidden files and directories in it)
ls
implementations that list more or less files depending on environments. However globs in several shells can be affected by the environment like with theFIGNORE
variable in ksh, GLOBIGNORE in bash, BASHOPTS in bash that can enable options like dotglob, nullglob. – Stéphane Chazelas Apr 25 '18 at 09:56exec
, then I expect thatdu *
will fail, too. I say “unlikely” because that limit is very large. – Scott - Слава Україні Jul 25 '19 at 14:00