9

I am using find to find names of databases that return some rows for a query.

$ find . -name 'sqlite.db' -exec sqlite3 "{}" 'SELECT * FROM table WHERE column1="value"' \; 

value|a|b|c|d

But I want the name of the database, so I tried -print which showed all the names

$ find . -name 'sqlite.db' -print -exec sqlite3 "{}" 'SELECT * FROM table WHERE column1="value"' \; 

/dir1/a/sqlite.db
value|a|b|c|d
/dir2/a/sqlite.db
/dir2/b/sqlite.db
/dir3/a/sqlite.db

Is there a way I can get only the files where the exit status of the command run is success.

Himanshu
  • 2,384
  • 2
  • 24
  • 42

3 Answers3

11

You just need to -print after the -exec. It is a short circuiting boolean and, and by putting -print before -exec, the print happens before the exec does.

find . -name sqlite.db -exec ... \; -print
William Pursell
  • 204,365
  • 48
  • 270
  • 300
1

sqite3 returns 0 even when there is not data is found matching the criteria. It returns false only when there is a error in the sql statement itself or in the arguments passed.

sqlite3 sqlite.db 'SELECT * FROM table WHERE column1="value"'

will return 0 even there is no matchin column in the database. You can combine command with grep for the find to work.

sqlite3 sqlite.db 'SELECT * FROM table WHERE column1="value" | grep value

so your find command becomes

find . -name 'sqlite.db' -exec sqlite3 "{}" 'SELECT * FROM table WHERE column1="value"' | grep value \;

EDIT:

The above doesn't work since exec cannot handle pipes. see How do I include a pipe | in my linux find -exec command?

find . -name "*.db" -type f | while read file ; do sqlite3 $file "SELECT * FROM table WHERE column1='value'" | grep value ; if [ $? -eq 0 ] ; then echo $file ; fi done

This I have tested and it works, but I am not sure whether this is the solution you are looking for.

Community
  • 1
  • 1
Santosh
  • 799
  • 7
  • 14
  • Thx. And this gives me grep: ';: No such file or directory' 'find: -exec: no terminating ";" or "+"'. Am I missing sth. – Himanshu Jan 30 '13 at 08:01
  • 1
    `find` with `exec` can handle a pipe just fine, but you need to invoke a shell: `find . -exec sh -c 'echo {} | grep .' \;` – William Pursell Jan 30 '13 at 19:05
0

You can get the exit status and test it in an if statement in order to do what you want.

The way to get this status is using $? variable. Here is a tutorial about it: http://tldp.org/LDP/abs/html/exit-status.html

If you want to add more code after find command, you can have a look to xargs to execute a shell script for each output line found by find, passing the results as arguments using xargs:

find . -name 'sqlite.db' | xargs <your_script>.sh

Besides, another solution in your case could be using AWK to execute the query for each find output row and analyze its result separately:

find . -name 'sqlite.db' | awk '{system("sqlite3 ..."); if () {} else {} }' -
arutaku
  • 5,937
  • 1
  • 24
  • 38
  • exec itself checks for the return status, and prints the file only when the status is sucess (0), so I think there is no need check explicitly. – Santosh Jan 30 '13 at 07:48