Can someone confirm that the following one liner will produce the total human readable size of all the directories which FIND locates as having log in the name?
find -type d -name *log* | du -hcs
Ready?
find . -type d -name '*log*' -print0 | xargs -0 du -hcs
*log*
in single quotes or else the shell will expand it before find
sees it.-print0
to separate the find output by null characters for xargs
xargs -0
to put each null-separated filename from find
into the command line of du
Easy, right? :)
find
goes to the standard input of du
and gets ignored. As a result, du -hcs
reports the total size of the whole current directory. The xargs
in the answer moves those filenames from standard input to the command line where du
will see them. In my /var
on cygwin, the command line from the question gives the same output as du -hcs
without the find
: 79M .
. The command line from the answer gives 1.1M ./log
, indicating it only processed ./log.
Your one-liner has two major issues:
find | du
passes the output of find
to the stdin of du
. However, du
completely ignores the standard input, so the find
filter is completely ignored, and the command you provided is in fact equivalent to du -hcs
. The solution is to use xargs
, which passes the list of files as arguments to du
, or du --files0-from=-
(GNU coreutils).\*log\*
) or with single quotes ('*log*'
), otherwise your shell will try to perform filename expansion and find
will possibly not see the asterisks at all.Some more improvements:
./log/log/
, both ./log/
and ./log/log/
would be passed to du
. The second directory would be ignored by du -s
, but you can increase performance of the find
command by adding the -prune
action. It will make sure that find
does not further descend into matched directories.-print0
(and -0
to xargs
) to avoid potential problems with e.g. newlines in file names, see serverfault..
) to make the find
command compatible to POSIX (and BSD).This is the final one-liner:
find . -type d -name '*log*' -prune -print0 | xargs -0 du -hcs
Keep in mind that -name
is case-sensitive. Personally I almost always use -iname
, which is case-insensitive.
Additional note: if you're using GNU coreutils' du
, you can use its --files0-from=-
option and pass the file paths directly to du
, omitting xargs
. According to the manual, ”this is useful when the list of file names is so long that it may exceed a command line length limitation.“
find . -type d -name '*log*' -print0 | du --files0-from=- -hcs