how to find files by name and content in linux or unix from the command line

So, you saved some information in a file somewhere in your hard drive sometime back and cannot find the file anymore. You vaguely remember the file name but don't know where it is, and obviously you have about 13247 file folders and thousands and thousands of files. The easiest way to find the file that you want is using one of the locate commands.

update the database

For the locate command to work, you should have the updatedb running. Usually the updatedb runs as a cron job and updates the file database about once a day with the file information. You can always run the updatedb command manually to update the database, if you think the file was saved or modified during the same day.

To update the database manually, run the updatedb from the command prompt

bash# updatedb

using slocate to find the file

Now, we can use either locate or slocate to find files. slocate is variation of locate which takes into consideration the security/permissions of the file while finding it. It means another user will not be able to find your files unless they have permissions to the file. I recommend installing and using slocate instead of locate. The options for both the commands are pretty much the same.

Now, let's say you saved a file with some drinks/cocktail recipes in some file somewhere which you want to find. The file name probably has drinks in its name. So to find all files with the word drinks in it we can do something like this:

bash# slocate drinks

Remember that the file names in unix is case sensitive, so "Drinks" is different than "drinks". But you can do a case insensitive search, if you are unsure about the case of the file name. The command line option  -i will do a case insensitive search for the word.

bash# slocate -i drinks

The other useful option that you can use with slocate is the regular expression syntax. The command line option -r or –regexp will allow you to use regular expressions to search for a file name.

rlocate and mlocate

There are other versions of locate command as well. The other variations of the locate command that you might want to check out are rlocate and mlocate.

rlocate behaves the same way as *slocate * and have similar options and syntax. The difference is that rlocate tries to maintain an always up-to-date database, instead of the standard database that updates about once a day.

mlocate is another variation which tries make the database maintenance and upkeep efficient. It tries to reuse the existing database rather than create a new one by scanning the file system every time.

using find command to find files

Another command which can be used to find the file is the find command. This is more useful when you want to search only a particular folder or location. It is also useful if your updatedb is not up to date or you do not have it installed on your system. Doing a find over your entire hard drive is probably going to be much slower, so use a folder for searching.

bash# find /home/me/recipes -name "*drinks*"

This will find all the files which has drinks in its file name. The file name expression in the find command is a regular expression, so we need to specify the "*" wildcard to match all the file names which has drinks in it. Also, it is case sensitive, which means to find Drinks, drinks or DRINKS, we will have to use the -iname option.

bash# find /home/me/recipes -iname "*drinks*"

So, locate and find commands are useful in finding files if we know the file names or part of the file name. But what if we want to search the contents of a file? Let's say we want to find the recipe for a particular martini, which means we will need to search the file content. We will have to use the grep command to do that.

using grep command to find files

bash# grep -r martini /home/me/recipes

will find files with the word martini in its contents. But it is case sensitive, so we will need to use -i switch for the case insensitive search. The -r switch does a recursive search, meaning it will search all the files and sub-directories in that folder.

bash# grep -ir martini /home/me/recipes

using find and grep

So, now let's say you want to search for a file with a specific file name and which contains a particular content. As an example, in order to search for a file with a file name drinks and contains the word martini it it, we can use the find command, with the grep command as in the example below

bash# find /home/me/recipes -iname *drinks* -exec grep -i martini "{}" \;

This will find all the files which has the word drinks in its file name and has the word martini in its content. You can now create script for this command, so that you do not have to type it in every time. I will show you a very rudimentary script, that takes three values: the directory to search, the file names and the word to search for.

find $1 -iname $2 -exec grep -i $3 "{}" \;

and you execute the script by using the command

$ scriptname /home/me/recipes drinks* martini

Now let's extend this with some shell script magic to search for files inside an archive file. For example, If we want to search for a particular class inside a set of jar files, we can use something like this:

bash# for x in $(find . -name "*.jar"); do echo $x; jar tvf $x | grep -i Martini; done

The above command will find all the jar files in the folder, and the jar command will list all the archive contents inside the jar file and the grep will find the class files which match the classname that has the word martini in them. You should be able to use the same format to search inside all different types of archive files, provided you change the jar command to the appropriate command to list the archive content.