Linux: xargs vs. exec {}

By Daniel Miessler on October 29th, 2006: Tagged as Linux | Sysadmin | Unix
  • dchen
    You can have the same behavior with find by replacing the ; with a +. To illustrate, try running the following:

    find . -exec echo {} \;
    find . -exec echo {} +
    find . -print0 | xargs -0 echo
  • Justin McBroom
    tomchuck,

    bash has no problem looping through a list of files with our without spaces, you just
    have to make sure and put quotes around the loop variable:

    for png in *.png ; do echo pngcrush "$png"; done
  • When using the -i or -I string replacement for xargs (needed for any
    complex operation such as the convert example above), then it
    becomes impossible for xargs to group the arguments together and
    it has to execute them one at a time as in -exec. If you change the
    example above to:

    # time find . -name “*.jpg” -print0 | xargs -0 -ifile ls file

    you'll see it has almost exactly the same running time as -exec.

    This dual behavior of xargs can be surprising - a complex command
    written with -i may work fine since it only receives one argument at
    a time, but break suddenly if the -i is removed and the command
    faces batched arguments. It's probably best to use the -exec
    option to find(1) wherever you would need to use -i in xargs to avoid
    this confusion.
  • tomchuk
    Mike,

    bash loops work great until you hit a filename with a space.
  • To those who mentioned caching, I performed the test at least ten times using both commands to produce the numbers I did. I ran into the caching issue as well on other systems, but on the system in question I think I was getting real numbers. Again, both numbers come from the command being run multiple times. I didn't run one without the cache and one with it.

    That, I agree, would have been lame...
  • Mike
    mikkom,

    If you're using 'bash' as your shell (you should be), it's often easier to just say 'for i in *.jpg; do convert file blah...
  • admp
    TD: it's filesystem kernel-level cache. This is simply incorrect method of benchmarking. May the author check inner details better next time. Kudos.
  • TD
    If you try the commands in the other order, i.e. xargs first then -exec the exec is faster, at least in my little test of finding all jpgs in my home dir. xargs took 2mins exec took 21 secs.

    /me wonders if find caches results or something to speed it up when you do a similar find afterwards.
  • What impant did harddrive caching have on your test?
  • mikkom:
    I'm not too familiar with xargs, but I think this find expression will do what you want:

    find . -maxdepth 1 -name '*jpg' -exec convert '{}' -resize 90x -crop 90×90 0 0 '{}' ';'

    I usually put '' around {} in case of spaces.
  • .. and if you are doing a hardcore batch job for 15000 files, are those 6 seconds of shell processing really that important?

    I use xargs but definitely for different reasons than few second difference... I'm not aware if the following example is even possible with -exec:

    ls *jpg|xargs -ifile convert file -resize 90x -crop 90x90 0 0 file
blog comments powered by Disqus

 

twitter_icon

Sample Original Content


Information Security

Tutorials and Primers

Culture & Society

Technology & Science

Politics

Philosophy & Religion

Miscellaneous

Tools & Projects


Blog Archives