DISQUS

danielmiessler.com | grep understanding: Linux: Harnessing The Über-Powerful Find Command (+xargs)

  • Name Required · 3 years ago
    you should mention how to redirect the permission denied messages

    find / -name required 2> /dev/null
  • Artifex · 3 years ago
    It might also be good to mention the standard technique for using find with tar.

    find . -daystart -mtime 0 > temp
    tar -cvf stuff.tar -T temp
    rm temp

    Generally you don't want to use xargs with tar and the create (c) flag, unless your sure that there are only a very few files.
  • Daniel Miessler · 3 years ago
    Ah, great comments; thanks!
  • Dave · 3 years ago
    Excellent stuf!
  • Lenny · 3 years ago
    I don't think the following command-line from your article:

    # Clean the images off of your *nix desktop
    find ~/Desktop -name "*.jpg" -o -name "*.gif" -o -name "*.png" -print0 | xargs -0 mv ~/Pictures

    will work as you expect. You'll want to wrap the find(1) -name tests in parentheses, otherwise you'll only list the *.png files.

    Also, the mv(1) command(s) that xargs(1) will generate, won't work because
    the last argument needs to be a directory. Assuming your Desktop directory
    looks like this:

    $ ls Desktop Pictures
    Desktop:
    bar.png foo.gif one.png three.jpg two.jpg

    Pictures:

    here's the results of running your original command-line:

    $ find Desktop -name "*.jpg" -o -name "*.gif" -o -name "*.png" -print0 | xargs -0 -t mv Pictures
    mv Pictures Desktop/bar.png Desktop/one.png
    mv: when moving multiple files, last argument must be a directory
    Try `mv --help' for more information.

    Here's a version that will work as you expect:

    $ find Desktop \( -name "*.jpg" -o -name "*.gif" -o -name "*.png" \) -print0 | xargs -0 -t mv --target-directory=Pictures
    mv --target-directory=Pictures Desktop/three.jpg Desktop/two.jpg Desktop/foo.gif Desktop/bar.png Desktop/one.png

    $ ls Desktop Pictures
    Desktop:

    Pictures:
    bar.png foo.gif one.png three.jpg two.jpg

    IIRC the --target-directory option is specific to the GNU version of mv(1).

    If you had a standard mv(1) command lacking the --target-directory option,
    you'd need to move one file at a time and xargs wouldn't provide much benefit
    over the -exec feature of find(1):

    $ find Desktop \( -name "*.jpg" -o -name "*.gif" -o -name "*.png" \) -print0 | xargs -0 -t -i mv {} Pictures
    mv Desktop/three.jpg Pictures
    mv Desktop/two.jpg Pictures
    mv Desktop/foo.gif Pictures
    mv Desktop/bar.png Pictures
    mv Desktop/one.png Pictures

    $ ls Desktop Pictures
    Desktop:

    Pictures:
    bar.png foo.gif one.png three.jpg two.jpg

    The -t option to xargs(1) is your friend. It traces the commands generated
    by xargs(1). If you want to be extra cautious, use -p instead and it will
    print each command-line and ask you if you want to proceed.