Is there a way to force the find
command to stop right after finding the first match?

- 801
- 1
- 9
- 35

- 12,884
7 Answers
With GNU or FreeBSD find
, you can use the -quit
predicate:
find . ... -print -quit
The NetBSD find
equivalent:
find . ... -print -exit
If all you do is printing the name, and assuming the filenames don't contain newline characters, you could do:
find . ... -print | head -n 1
That will not stop find
after the first match, but possibly, depending on timing and buffering upon the second match or (much) later. Basically, find
will be terminated with a SIGPIPE when it tries to output something while head
is already gone because it has already read and displayed the first line of input.
Note that not all shells will wait for that find
command after head
has returned. The Bourne shell and AT&T implementations of ksh
(when non-interactive) and yash
(only if that pipeline is the last command in a script) would not, leaving it running in background. If you'd rather see that behaviour in any shell, you could always change the above to:
(find . ... -print &) | head -n 1
If you're doing more than printing the paths of the found files, you could try this approach:
find . ... -exec sh -c 'printf "%s\n" "$1"; kill -s PIPE "$PPID"' sh {} \;
(replace printf
with whatever you would be doing with that file).
That has the side effect of find
returning an exit status reflecting the fact that it was killed though.
We're sending the SIGPIPE signal instead of the default SIGTERM to avoid the message that some shells display when parts of a pipe line are killed with a signal. They generally don't do it for deaths by SIGPIPE, as those are naturally happening (like in find | head
above...).

- 544,893
find . -name something -print -quit
Terminates find after the first match after printing it.
Terminate find after a specific amount of matches and print results:
find . -name something -print | head -n 5
Surprisingly enough - head now terminates string after 5 matches, though I do not know how or why.
It is very easy to test. Just let find search a on root which would result thousands, maybe even more matches while taking at least a minute or more. But when piped into "head" "find" will terminate after the specified amount of lines defined in head (default head shows 10, use "head -n" to specify lines).
Note that this will terminate after "head -n" reaches the specified newline character count and therefore any match that contains multiple newline characters will count accordingly.
-
I have also observed this 'program terminates after head is done with its output' phenomenon, but not consistently across shells. I think this merits its own question - fortunately for bash the answer is already at StackOverflow's Bash: Head & Tail behavior with bash script. That gives enough information for me to conclude that whether the program terminates or continues to execute in the background depends on its response to SIGPIPE - killing is the default. – sage Oct 16 '15 at 16:04
-
I meant 'across programs/shells', but apparently unix.stackexchange.com would prefer that I log this as a second comment rather than letting me edit my first comment (this is a stackexchange, site-specific policy decision). Also, I now see that @Ruste commented to this effect at the top, which did not help me initially since I went straight to answers... – sage Oct 16 '15 at 16:12
When running find with -exec
use -quit
after the \;
, otherwise the command execution will be skipped. For example:
find -name "myfile*" -exec echo "Found {} and Quit" \; -quit
Found ./myfile1 and Quit
But when using -quit before -exec:
find -name "myfile*" -quit -exec echo "Found {} and Quit" \;
# Nothing was executed

- 1,031
grep also returns if used with the flag -m
, so with
find stuff | grep -m1 .
it will return after the first line printed by find.
The difference between this and find stuff -print -quit | head -1
is that if the search is fast enough grep might not be able to stop the process in time (doesn't really matter though), while if the search is long it will spare find to print a lot of not needed lines.
this instead works with busybox find, although since busybox grep also has -m
it is not really needed
find /tmp/stuff -exec "sh" "-c" "eval 'echo {}; { kill \$PPID; }'" \;
this will spit out a message about the find process having received the (usually) sigterm signal, but this output belongs to the running shell, not the find command so it does not mess with command output, meaning pipes or redirects will output just the line matched by find.

- 325
For entertainment purposes, here's a lazy find generator in Bash. This example generates a ring over the files in the current directory. Read however many you want then kill %+
(maybe just 1)
#!/usr/bin/env bash
unset -v files n
trap 'kill "$x_PID"' EXIT
coproc x while :; do
find . -type f -maxdepth 1 -exec sh -c "$(</dev/fd/3)" _ {} +
done 4<&0 <<\EOF 3<&0 <&4-
for x; do
read -r _
printf '%s\0' "$x"
done
EOF
while
echo >&${x[1]}
IFS= read -rd '' -u "$x" 'files[n++]'
do
printf '%q ' "${files[@]}"
echo
sleep .2
done

- 752
I Didn't catch a bit of the ring stuff answer, so i re-implemented like this: takes 3 arguments 1st: working directory 2nd: extension to find 3rt: number of results to show
#!/usr/bin/env bash
if [ -z "${1}" ]
then
CWD="$(pwd)"
else
CWD="${1}"
fi
if [ -z "${2}" ]
then
EXT="wma"
else
EXT="${2}"
fi
if [ -z "${3}" ]
then
MAX=1
else
MAX="${3}"
fi
TMPFILE=$(tempfile -p mtfind-)
find ${CWD} -iname "*.${EXT}" -type f 2>/dev/null 1>${TMPFILE} &
PID=$!
WCL=0
CONDITION=1
while [ ${CONDITION} ]
do
WCL=$(wc -l ${TMPFILE} | cut -d " " -f1)
CONDITION=$(echo "${WCL}<${MAX}"| bc -l)
if [ -d "/proc/${PID}" ]; then
echo -ne "."
else
echo "find ended"
head -n${MAX} "${TMPFILE}"
rm -f ${TMPFILE}
exit
fi
sleep .02
done
kill -9 ${PID}
head -n${MAX} "${TMPFILE}"
rm -f ${TMPFILE}
if [[ $(find ... -print -quit) ]]; then ...
It just tests whether find printed anything at all. – Tobia Dec 19 '14 at 18:26$(…)
part in quotes in case you are using just the single brackets ([ … ]
). – phk Jan 14 '17 at 23:18[
is a standard command. It's not so much that command that is horrible but the way Bourne-like shells parse command lines.[[...]]
is a ksh construct that has issues of its own in various shells. For instance, until recently[[ $(...) ]]
wouldn't work inzsh
(you needed[[ -n $(...) ]]
). Except inzsh
, you need quotes in[[ $a = $b ]]
, the[[ =~ ]]
has incompatible differences between implementations and even between versions for bash and several bugs in some. Personally, I prefer[
. – Stéphane Chazelas Jan 16 '17 at 15:55...
? . – kyb Jul 06 '18 at 17:23-exec
is the answer by Noam placing-quit
after\;
not a much easier and better way? – Kvothe May 11 '23 at 14:31kill -s PIPE
was shown mainly forfind
implementations that don't support those non-standard-exit
or-quit
. Beware however that if you dofind ... -exec cmd {} ';' -quit
,-quit
will only be run ifcmd
succeeds. You'd needfind ... '(' -exec cmd {} ';' -o -true ')' -quit
to runcmd
only once regardless of whether it succeeds or not (-true
being another GNU extension). – Stéphane Chazelas May 11 '23 at 14:38