With GNU find
, it is easy to pipe to xargs
. A typical (useless) example:
find /var/log -name "*.log" | xargs dirname
This returns all the directory names containing some log file.
The same command with BSD find
does not work, ending with:
usage: dirname path
That is xargs
is unable to pass file list entries to dirname
.
BSD find
's manpage mentions the -exec
and -execdir
options, stating "This behaviour is similar to that of xargs(1)."
-exec utility [argument ...] {} + Same as -exec, except that ``{}'' is replaced with as many pathnames as possible for each invocation of utility. This behaviour is similar to that of xargs(1).
-execdir utility [argument ...] {} + Same as -execdir, except that ``{}'' is replaced with as many pathnames as possible for each invocation of utility. This behaviour is similar to that of xargs(1).
Each time I fall back on these two flags, I have to read the documentation again. I seem unable to remember their usage! Also, I am concerned with script portability across GNU/BSD systems, basically Linux, Open/FreeBSD, and MacOS.
Any way to pipe BSD find
to xargs
, or -exec
is really the only option?
Both GNU and FreeBSD version of xargs
support a way to pass the strings from stdin to the command as part of the -I
flag. All you need to is
find /var/log -name "*.log" | xargs -I {} dirname -- "{}"
The GNU xargs
page says about the flag as
-I replace-str
Replace occurrences ofreplace-str
in the initial-arguments with names read from standard input.
This provides an alternate way than using -exec
or -execdir
. However, having said, that using -exec
is not too complex for your case.
find /var/log -name "*.log" -type f -exec dirname "{}" \;