If the searching command has no way to stop after the first match, you can filter its results and keep only the first output line: command 'pattern' /path/to/file | head -n 1
. The command will receive a SIGPIPE signal when head
exits, so it might go on looking for a few more matches due to buffering but it will stop before the end of the file if there are a lot of matches.
Since you need to run a shell command (to set up the pipe), you need to invoke sh
from find
. Mind the quoting: you need one layer of quotes for the outer shell, and another for the shell started by find
. You can put single quotes around the inner shell command and work in single quotes with the '\''
hack (end single quote literal, \'
for a literal single quote, and start a new single quote literal in the same breath), this way you don't need any different quoting in the pattern (unless the pattern contains a '
that you represented as '\''
, in which case you'll need to make that '\'\\\'\''
).
find dir -iname '*.ext' -exec sh -c 'command '\''pattern'\'' "$0" | head -n 1' {} \;
Instead of worrying about quoting the pattern, you can put it outside and pass it as a parameter.
find dir -iname '*.ext' -exec sh -c 'command "$0" "$1" | head -n 1' 'pattern' {} \;
It will be slightly faster to invoke only one shell and loop over the files.
find dir -iname '*.ext' -exec sh -c '
for f; do command "$0" "$f" | head -n 1; done
' 'pattern' {} +