Thursday, October 23, 2008

So what is so great about find?

Why do people not like find? It is a nice command to have. I gather that there is no "find" in BSD and that find is "impure" (I am not sure about both) Well, frankly, it makes no difference to me, as a user, whether a command is pure or impure. Find is a simple slick and helpful command and that is what I care about. As for BSD, get the sources and compile!

Anyway, there is an alternative to find (albeit lame). It is "locate".
Basic syntax :

>> locate [pattern]

(Don't mind the square brackets. '<' brackets makes google think that I am writing some xml doc. So, a quick fix) Locate merely searches the database of names that was created by "updatedb" command. updatedb is periodically scheduled by crond. So, your database is automatically updated. You don't need to worry about that. One advantage of this approach is that the search is lightning fast. If you compare the performance of locate and find, locate would win by light years! Also, the syntax of locate is deceptively simple. Merely, "locate {pattern}"
But, as every girl you like is always taken, locate has its own drawbacks.

1) locate command doesn't check whether the file actually exists on your machine. It simply consults the database and gives back the results. (Thus, after an updatedb, you delete a file, you still get it in the locate results until crond schedules another updatedb). You can pass "-e" to locate to avoid this condition. -e checks whether the file actually exists.

2) If you create a new file, it won't appear in the locate results for a while. (Until crond schedules an updatedb)

3) There is no way you can ask locate to search only within a particular directory. You have to search the entire directory tree, always. This, in my opinion, is the worst drawback of locate.

Some other options that could be passed to locate:
-i : ignore case
-b : match basename only. (i.e. the final component of the whole name)
-e : check if file exists
-E : print only files that do not exist, but were there when database was made.

Find is good.
With find you can search a part of the direcotry tree. The basic syntax is

>> find [directory to search in] [options]

eg. >> find . -name "Linux"
the beauty of the command is that, you can have many many search parameters. Like:
1) -name [pattern]
Search name of the file
2) -user [username]
Search for files owned by this particular user
3) -perm -{octal permission bits}
Search for files with this permissions.
4) -type [c]
Search for files only of type . (eg. b for block. p for pipe etc etc)
and many more. Check out the man page. You can combine the above options.
eg. >> find . -name "Linux" -user httpd

Also, with find the expression part can be "expression" "!expr" "expr or expr" "expr and expr" etc etc. Quite handy!

What more? You can format your output as per you wish. check the -print option in the find man page. Havn't found the need to use this one, but such options are good for writing scripts.

When you search in "/", find unecessarily searches the mounted windows paritions too? No prob, pass "-mount" and it won't !! It'll skip all mounts.

With find, you can have more control over the search. But the downside is that find is terribly and horribly slow.

As a third lame option. You can define an alias. Something like

>> alias myfind='updatedb; locate'

So, "myfind" becomes a new command which expands to 'updatedb; locate'. Neat, eh?
although, the overhead of updatedb might not always be acceptable. In those cases, you can simply use locate. updatedb, btw, is NOT very slow. So, it is a better option than find, if you don't want too tight a control on your search.

Enjoy searching!!

(PS: Lookout for the next post on grep)


Kedar said...

'locate' takes a regexp as input as well. So if you wish to search for a file with 'readme' in it, and restrict the search only to '/usr/share/doc/abc/' you can always say:
locate '/usr/share/doc/abc/*readme*'

@$%deja vu$% said...

Too much effort if I am already in the directory to be searched!! :)

Although, on second thoughts, I can always say
>> locate $PWD*readme*


Vedang said...

lol.. i asked for a grep tutorial.. instead you whet my appetite with locate and find post (Yes, I know, shameless blog promotion ;))
Looking forward to the grep tutorial, make it nice and in detail!