You can test for file attributes that none of the find
builtin
tests check. To do this, use xargs
to run a program that filters
a list of files printed by find
. If possible, use find
builtin tests to pare down the list, so the program run by xargs
has less work to do. The tests builtin to find
will likely run
faster than tests that other programs perform.
For reasons of efficiency it is often useful to limit the number of
times an external program has to be run. For this reason, it is often
a good idea to implement “extended” tests by using xargs
.
For example, here is a way to print the names of all of the unstripped
binaries in the /usr/local directory tree. Builtin tests avoid
running file
on files that are not regular files or are not
executable.
find /usr/local -type f -perm +a=x | xargs file | grep 'not stripped' | cut -d: -f1
The cut
program removes everything after the file name from the
output of file
.
However, using xargs
can present important security problems
(see Security Considerations). These can be avoided by using
-execdir. The -execdir action is also a useful way of
putting your own test in the middle of a set of other tests or actions
for find
(for example, you might want to use -prune).
To place a special test somewhere in the middle of a find
expression, you can use -execdir (or, less securely,
-exec) to run a program that performs the test. Because
-execdir evaluates to the exit status of the executed program,
you can use a program (which can be a shell script) that tests for a
special attribute and make it exit with a true (zero) or false
(non-zero) status. It is a good idea to place such a special test
after the builtin tests, because it starts a new process which
could be avoided if a builtin test evaluates to false.
Here is a shell script called unstripped
that checks whether its
argument is an unstripped binary file:
#! /bin/sh file "$1" | grep -q "not stripped"
This script relies on the fact that the shell exits with the status of
the last command in the pipeline, in this case grep
. The
grep
command exits with a true status if it found any matches,
false if not. Here is an example of using the script (assuming it is
in your search path). It lists the stripped executables (and shell
scripts) in the file sbins and the unstripped ones in
ubins.
find /usr/local -type f -perm +a=x \ \( -execdir unstripped '{}' \; -fprint ubins -o -fprint sbins \)