LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   find command return true if a file was found (http://www.linuxquestions.org/questions/programming-9/find-command-return-true-if-a-file-was-found-881400/)

catalint 05-18-2011 09:33 AM

find command return true if a file was found
 
Hello there,

Anyone knows how to manage the find command to return true or false if a file was found/or not? I tried to man find but didn't found anything.

Regards,

Chirel 05-18-2011 09:39 AM

Hi,

the find command will only return non zero value on error, so it will return 0 if it find or not file.
A solution could be to pipe the output to grep -q who will return non zero if not found.
Something like that :
Code:

find . -name 'filename' | grep -q filename && echo "File found" || echo "File not found"
I'm sure there are more optimized solution, but it's the first that came to me.

Solution 2:
Code:

[ -n "$(find . -name 'filename' 2>/dev/null)" ] && echo "File found" || echo "File not found"

Ramurd 05-18-2011 09:39 AM

The return value of find ./ -name does_not_exist = 0; Also find ./ -name does_exist returns 0.

So, what can you do?

Code:

if [ $(find ./ -name does_exist | wc -l) -gt 0 ]
then
  echo "Found something"
else
  echo "Found nothing
fi

wc -l will count the lines, which will be >0 if something was found, and 0 if nothing was found.

Edit: The solution looks different, but is essentially the same; Chirel beat me to it ;-)

Nominal Animal 05-18-2011 11:29 AM

I recommend using a short-circuited version of Chirel's solution:
Code:

FILE=`find . -name 'filename' -print -quit`

if [ -n "$FILE" ]; then
    echo "Found $FILE"
else
    echo "Not found."
fi

The -quit option tells find to not do any further searches after the first match is found. That way it prints at most one file name.

MTK358 05-18-2011 12:03 PM

Code:

if [ "$(find -option1 -option2)" '!=' '' ]
    # find found something
else
    # no matching files found
fi


gnashley 05-18-2011 02:38 PM

case is more efficient than [ or test when you can get by with simple pattern matches.
Code:

case `find . -name 'filename' -print -quit` in
  '') echo 'No filename found' ;;
  *) echo 'Found filename' ;;
esac


Nominal Animal 05-18-2011 03:34 PM

Quote:

Originally Posted by gnashley (Post 4360170)
case is more efficient than [ or test when you can get by with simple pattern matches.

Hey, gnashley, thanks for the heads up: I didn't know that. In fact, I was sceptical enough to test:
Code:

time bash -c 'for F in `seq 1 10000` ; do true ; done'
time bash -c 'for F in `seq 1 10000` ; do true ; case "$F" in 50) echo 1 ; esac ; done'
time bash -c 'for F in `seq 1 10000` ; do true ; [ "$F" == "50" ] && echo 1 ; done'
time bash -c 'for F in `seq 1 10000` ; do true ; if [ "$F" == "50" ]; then echo 1 ; fi ; done'

on an Atom N270 laptop and Bash 4.1.5, the real times were 0.285s, 0.490s, 0.733s and 0.745s, respectively; meaning that ten thousand cases took +0.20s, [s +0.45s, and ifs +0.46s real time. In other words, cases took less than half the time compared to [s or ifs. Funny! But I wonder how on earth did you come across that info? ;)

MTK358 05-18-2011 03:42 PM

Quote:

Originally Posted by Nominal Animal (Post 4360217)
I wonder how on earth did you come across that info? ;)

It's faster to do globbing (which is part of the shell) than it is to launch the test command.

Nominal Animal 05-18-2011 05:40 PM

Quote:

Originally Posted by MTK358 (Post 4360229)
It's faster to do globbing (which is part of the shell) than it is to launch the test command.

Obviously. The funny bit is that Bash does not execute test or [ for these tests, it does them internally, just like the globbing. You can verify it yourself by straceing a bash test:
Code:

strace -f -F bash -c '[ -e somefile ] && echo "somefile exists" || echo "somefile does not exist"'
Bash will only exec the external binary if you explicitly tell it to, for example by specifying the full path:
Code:

strace -f -F bash -c '/usr/bin/[ -e somefile ] && echo "somefile exists" || echo "somefile does not exist"'

gnashley 05-19-2011 03:14 AM

Sure, `type test` or `type [` will tell you that the internals are being used. I discovered that case was faster when I tried to optimize some really slow code where I was using brackets in multi-choice if-elif-then pattern comparisons. In my routine 'case' ran in about 30% of the time as using brackets. In the OP's example, the difference would probably less.

Chirel 05-19-2011 04:21 AM

Hi,

Fun to see where a simple question can bring a post :)

I must admit that the Nominal Animal find . -name 'filename' -print -quit is really nice.
No subcall to grep et no full tree traversal if the file is found in the begining . . . Good one.

catalint 05-19-2011 07:16 AM

Hei you gurus ,
my issue is that on solaris -quite doesn't work. any workaround for this? :(

thx

Nominal Animal 05-19-2011 07:52 AM

Quote:

Originally Posted by catalint (Post 4360773)
my issue is that on solaris -quite doesn't work. any workaround for this? :(

Oh, right, -quit isn't supported by all finds. Fortunately, I have a pretty devious workaround you can use instead:
Code:

FILE=`find . -name 'filename' -print -exec sh -c 'kill -TERM $PPID' ';'`
case "$FILE" in
    '') ;;
    *)  echo "Found '$FILE'." ;;
esac

Whenever the find command finds a file, it will print the file name, then exec an sh subshell that will send a TERM signal to its parent, terminating the find command. Although that will also result in exit status 143 ("killed by TERM" in Linux and Solaris at least), the most reliable way is still to check if FILE is non-empty.


All times are GMT -5. The time now is 03:01 PM.