command line - Two ways - two different results

07
2014-07
  • Tony

    I ran two seperate commands each one produced a different number. Can anyone help me figure out why?

    find -type d -name *log* | du -hcs
    
    find . -type d -name '*log*' -print0 | xargs -0 du -hcs
    
  • Answers
  • JdeBP

    I'm sure that the downvoter(s) thought that the way to figure out why was

    man du
    and wondered why you hadn't read the manual.

    Ironically, whilst this is indeed true for the BSDs, on Linux distributions this isn't the way to find out, because the GNU manual page is missing some fairly basic stuff. Linux users have to run

    info coreutils du
    to see documentation with one very important sentence in.

    It's the second sentence (third in OpenBSD) of the manual page for the BSD du command.

    So even though your wildcard — in your command rather than the corrected version that was given to you in an answer — is (potentially) expanded incorrectly in your find command, that doesn't make a single hap'orth of difference. Whatever your find command writes to its standard output, it is entirely ignored by the du command.

    From the manual, which explicitly states what is happening, combined with what was already stated in that answer in its third bullet point, it should be blindingly obvious why you're seeing different behaviours and results between your command and the corrected one. Prepare to kick yourself. ☺

    Further reading

    • du. MacOS 10 manual pages. Apple corporation.
    • du. FreeBSD 9.2 manual pages. 2012-11-04.
    • du. NetBSD 6.1.3 manual pages. 2006-09-24.
    • du. OpenBSD 5.4 manual pages. 2014-02-14.
    • du. DragonFly BSD 3.7 manual pages. 1994-04-01.

  • Related Question

    command line - find: -exec vs xargs (aka Why does "find | xargs basename" break?)
  • quack quixote

    I was trying to find all files of a certain type spread out in subdirectories, and for my purposes I only needed the filename. I tried stripping out the path component via basename, but it did't work with xargs:

    $ find . -name '*.deb' -print | xargs basename 
    basename: extra operand `./pool/main/a/aalib/libaa1_1.4p5-37+b1_i386.deb'
    Try `basename --help' for more information.
    

    I get the same thing (exactly the same error) with either of these variations:

    $ find . -name '*.deb' -print0 | xargs -0 basename 
    $ find . -name '*.deb' -print | xargs basename {}
    

    This, on the other hand, works as expected:

    $ find . -name '*.deb' -exec basename {} \;
    foo
    bar
    baz
    

    This happens on up-to-date Cygwin and Debian 5.0.3. My diagnosis is that xargs is for some reason passing two input lines to basename, but why? What's going on here?


  • Related Answers
  • akira

    because basename wants just one parameter... not LOTS of. and xargs creates lots parameters.

    to solve your real problem (only list the filenames):

     find . -name '*.deb' -printf "%f\n"
    

    which prints just the 'basename' (man find):

     %f     File's name with any leading directories 
            removed (only the last element).
    
  • perlguy9

    Try this:

    find . -name '*.deb' | xargs -n1 basename
    
  • John T

    basename only accepts a single argument. Using -exec works properly because each {} is replaced by the current filename being processed, and the command is run once per matched file, instead of trying to send all of the arguments to basename in one go.