Recently, I’ve seen a lot of suggestions along the lines of:
find . -name foo -exec ls -l {} ;
This is incredibly inefficient, because for each and every matching
file, ls will be executed. Fortunately, we can do better by
using xargs. xargs takes a list of lines from stdin
and uses them to build up a command line. It takes special care to not
exceed the maximum command line length by splitting the input up into
multiple commands if it is needed. So, with that knowledge, we can
replace our original command with:
find . -name foo | xargs ls -l
There is one slight problem with this command; it isn’t space-safe.
xargs splits arguments on whitespace, so “file name” will be
incorrectly passed to the command as “file” “name”. Fortunately,
xargs has an option to delimit parameters by the null
character, and as our luck would have it, find has a suitable
option to produce output in this format. This means our command is
now:
find . -name foo -print0 | xargs -0 ls -l
mlocate can do something similar:
locate foo -0 | xargs -0 ls -l
GNU find has one more trick up its sleeve. It has a modified version
of -exec that will do the same thing as xargs, so we could have
written our original command as:
find . -name foo -exec ls -l {} +
Every process is sacred; every process is great. If a process is wasted, God gets quite
irate. Please make sure you try to use one of the latter forms and not the
first form, and make a happy deity. 🙂
on said:
I assume that you are using “ls” as an example command since find has an “-ls” option which will not need any additional processes.
on said:
I’m a newly converted fan of GNU xargs’ -n 1 -P 10 (or whatever) for intensive jobs like compiling or encoding.
on said:
You could just do
ls -l **/name
with zsh and bash4.
zsh also has zargs, which is used like this:
zargs — **/name — ls -l
on said:
You could just do
ls -l **/name
with zsh and bash4.
zsh also has zargs, which is used like this:
zargs — **/name — ls -l
on said:
“GNU find has one more trick up its sleeve.[…] -exec ls -l {} +”
Just for clarification “-exec … +” is not a GNUism. It is part of the Susv3/Posix standard and e.g. the find implementations on *BSD supported this before GNU findutils.
on said:
“GNU find has one more trick up its sleeve.[…] -exec ls -l {} +”
Just for clarification “-exec … +” is not a GNUism. It is part of the Susv3/Posix standard and e.g. the find implementations on *BSD supported this before GNU findutils.
on said:
“GNU find has one more trick up its sleeve.[…] -exec ls -l {} +”
Just for clarification “-exec … +” is not a GNUism. It is part of the Susv3/Posix standard and e.g. the find implementations on *BSD supported this before GNU findutils.
on said:
Why not simply ‘find . -name foo -ls’ ?
on said:
As a side note and interestingly, many people uselessly write the dot: “find . arguments”.
By default find runs on the current directory so there is no need to specify it: “find arguments” is shorter.
I was telling it to a friend lately, just as he showed me that I could write “ln myfile” more concisely than “ln -s myfile .” Same stuff.
on said:
(oops in the former comment: I meant “ln -s” obviously in both cases!)