Previous: Delete Files, Up: Actions

3.5 Adding Tests

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 shell exiting 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 \)