Finding and Locating Files

Howto search for files with Linux

Finding files with the Locate command

The "locate" command is a very fast and efficient way of locating files quickly. The reason the locate command will outperform the find command on speed is due to the fact that its locations are stored in an internal database(s). The databases are created by a process called updatedb which normally runs on a cron timer. The locate command matches on any part of a pathname.

john@john-desktop:~$ locate updatedb

In the above example we passed the pattern "updatedb" to the locate command. The output from this command returned almost instantly. As you can see any file or program that contained the pattern "updatedb" was returned. The smaller the pattern you pass to the locate command, can increase the results significantly:

john@john-desktop:~$ locate updated

In the above example we changed the pattern from "updatedb" to "updated". The locate command then returned more output as the pattern matched more files.

updatedb : The majority of Linux systems would probably use a cron job to initiate the running of the updatedb process. If you have a busy system, you may want to amend this job to run once a week or during a quiet period. A lot of disk activity will take place whilst the updatedb process is running. More information can be found in the man pages or by issuing the "updatedb --help" command.

slocate : On some Linux systems the locate command has been replaced by another version of the command called "slocate". If you were wondering, slocate stands for "Secure Locate". The slocate command stores permission in its database. This stops normal users of the system from looking into directories that they would not normally have permission to look into. The syntax and usage of the command is the same as the standard locate version.

Find Command Examples

Basic Find Commands Explained

The first find command example literally searched through the root filesystem "/" for a file named "findme.txt". If the file is found, then it is displayed to your screen.

find / -name findme.txt -type f -print

In the above example we specified the "type -f " to specify that we are looking for a regular files only. If you don't specify the type, then you may get returned directories and other filesystem objects. The "-print" option specifies that the output goes to standard out (your screen). although it is good practise to use the "-print" option. It is no longer necessary on modern Linux systems as this is the default option.

find /usr /home -name findme.txt -type f -print

In the above example, we have specified two separate locations to search for the regular file "findme.txt". If you wanted to search in your current directory and all sub directories, then you can issue a command like:

find . -name Chapter1 -type f -print

The next example find command will search through the directory "/home/john" looking for any files that begin with the characters "landof". The pattern will match any files that start "landof".

find /home/john -name "landof*" -type f -print

The next example searches through the directory looking for any files that have the extension ".sh".

find /home/john -name "*.sh" -type f -print

Finding Directories with the find command

As we saw earlier, we can specify the file type with the "type" parameter. If we are looking for directories, then we can change our parameter to "-type d" . This narrows our search to directories only.

find /home/john -type d -name test -print

In the above example we search for any directories that are called test that are located under the "/home/John" area.

Excluding files in your results

Sometimes you may wish to search for a list of files, however, you may also want to exclude certain files types:

find /home/john/scripts -type f -not -name "*.ksh" -print

In the above example, we will search for all file types except for any files that have the ending ".ksh". To find all files that don't match a pattern, we use the "-not" flag.

Searching using mixed case sensitivity

Using the same syntax as we have used previously, we can instruct the "find" command to ignore the case of its pattern. This can be achieved by altering the "-name" parameter to read "-iname".

find . -iname test

The above will search for any files that match the pattern of "test", "Test", "TEST" and so on.... By adding the "-type d" or "-type f", you can switch between searching for files or directories.

Finding files that contain specific text

One of the major powers of the Linux command line is the ability to combine multiple commands together to function as one. In the following examples we will introduce you to a new command "grep" . More details of the "grep" command will be covered later in this section.

In the following example, we are going to search for all files that end with the ".sh" extension and contain the characters "landoflinux". The "-l" argument that is passed to the "grep" command instructs grep to print only the filename where a match is found.

find . -type f -name "*.sh" -exec grep -l landoflinux {} \;

In the above example, the "{}" contain the result of any matches found by the "find" command. This is then used for the basis of the "grep" command to run against.

find . -type f -name "*.sh" -exec grep -il landoflinux {} \;

The above example is almost the same as the previous example, however, this time we have added and extra parameter to the grep command. "-i" when used in conjunction with the "grep" command will then ignore the case of the filename. So if any files found that ended in ".sh" and contained the text "Landoflinux" or "landoflinux" or "LANDOFLINUX", then these would be classed as a match.

Changing permissions on found files

In the following example, we are going to search the "/home/john/script" area looking for any scripting files that have the extension ".sh". Any files found will then have their permissions altered by the "chmod" command.

find /home/john/script -name "*.sh" -type f -exec chmod 644 {} \;

In the above example, any files that end ".sh" will have their permissions altered to "644" or "rw-r--r--". Basically we will be removing the execute permissions if they were already set!

List all found files with "ls"

Quite often you will have a requirement where you will have to sort through files checking their permissions, creation date etc..
Thankfully there is an easy way to do this with the find command used in conjunction with the "ls" command".

find . -name "*.sh" -exec ls -ld {} \;

In the example above, we see that we have used the "-l" option on the "ls" command to give a long listing of out output. Also we have added the "-d". This reports back the directory information all on the same line.

Find and Delete files with the Find command

The following command is very useful, however, as always when we use a command that can be destructive, great care and attention must be given.

find . -type f -name "Tes*" -exec rm {} \;

Any files that begin "Tes" of a file called "Tes" will be passed to the "rm" command for deletion. Although this is very useful, it can also be very dangerous. Any easy way to test you logic first would be to modify the command slightly by substituting the "rm" command with "ls". Also, you could modify the "-name" parameter to "-iname" to ignore case.

find . -type f -name "Tes*" -exec ls -l {} \;

If you are then happy that these files can be deleted, then go ahead with the "rm" version.

Finding files with multiple extensions

Sometimes you may wish to search for files with more than one file type. You might want to search for scripts that have an extension of ".sh" and also perl scripts that have an extension of ".pl". Thankfully, this is very easy to achieve.

find . -type f \( -name "*.sh" -o -name "*.pl" \)

To add further patterns to search for, simply add another "-o" option to your command line.

Finding files by their modification time

Locate all files and directories within the current directory that have been modified in the last 7 days.
To limit the search to files, add the "type -f" option and for directories only add the "type -d" option.

find . -mtime -7 -print

Find files by their permissions settings

The following example finds any file in the current directory that has its permission set to read (symbolic method):

find . -perm -g=r -type f -exec ls -l {} \;

The example below demonstrates the difference between the "-perm -g=r" and "-perm g=r ". The latter find command only finds files whose group is set to read.

john@john-desktop:~/test_examples$ find . -perm -g=r -type f -exec ls -l {} \;
-rwxrwxrwx 1 john john 0 Jan 22 21:16 ./file3
-rwxrwxr-x 1 john john 0 Jan 22 21:16 ./file1
----r----- 1 john john 0 Jan 22 21:32 ./file<
-rw-rw---- 1 john john 0 Jan 22 21:27 ./file4
-r--r--r-- 1 john john 0 Jan 22 21:16 ./file2
john@john-desktop:~/test_examples$ find . -perm g=r -type f -exec ls -l {} \;
----r----- 1 john john 0 Jan 22 21:32 ./file

Find files by Octal permissions

This particular method is very handy for checking permissions on multiple files:

john@john-desktop:~/test_examples$ find . -perm 040 -type f -exec ls -l {} \;
----r----- 1 john john 0 Jan 22 21:32 ./file
john@john-desktop:~/test_examples$ find . -perm 777 -type f -exec ls -l {} \;
-rwxrwxrwx 1 john john 0 Jan 22 21:16 ./file3

Find empty files - Zero bytes in size

If you ever need to find files that are zero bytes in size, you can issue the following command: find . -empty

john@john-desktop:~/test_examples$ ls -l
total 12
----r----- 1 john john  0 Jan 22 21:32 file
-rwxrwxr-x 1 john john 29 Jan 22 21:52 file1
-r--r--r-- 1 john john  0 Jan 22 21:16 file2
-rwxrwxrwx 1 john john 29 Jan 22 21:52 file3
-rw-rw---- 1 john john 29 Jan 22 21:52 file4
john@john-desktop:~/test_examples$ find . -empty

Find the 10 Largest files in the current directory

This next command is very useful if you are trying to locate the largest 10 files within the current directory.

john@john-desktop:~/Documents/Weather$ find . -type f -exec ls -s {} \; | sort -n -r | head -10
9304 ./Riddle_et_al_accepted_withFigs.pdf
7624 ./11_Scaife_Stratosphere.odp
3976 ./long_range_forecast_winter_2012-13_full_report.pdf
3388 ./weather_lecture2.pdf
2012 ./Weather_&_Climate.pdf
1944 ./weatherwise_ws1080pc-solar_manual_a.doc
1912 ./FMH1.pdf
1680 ./weather_lecture3.pdf
1444 ./weather_lecture1.pdf
1084 ./Understanding the GFS charts-2nd version-13 sept 10.pdf

Find newer files than specified file

This command allows us to find files that are newer than the specified file:

john@john-desktop:~/test_examples$ ls -l
total 12
----r----- 1 john john  0 Jan 22 21:32 file
-rwxrwxr-x 1 john john 29 Jan 22 21:52 file1
-r--r--r-- 1 john john  0 Jan 22 21:16 file2
-rwxrwxrwx 1 john john 29 Jan 22 21:52 file3
-rw-rw---- 1 john john 29 Jan 22 21:52 file4
john@john-desktop:~/test_examples$ find . -newer file

Find files by size

In the following example, we will learn how to find files greater than a specific size, files smaller than a specific size or files equal to a given size.

john@john-desktop:~$ find . -size +1000M
./VirtualBox VMs/CentOS/CentOS.vdi
./VirtualBox VMs/Open SUSE 12.1/Open SUSE 12.1.vdi

john@john-desktop:~$ cd Puppy_Linux_Installer/
john@john-desktop:~/Puppy_Linux_Installer$ ls -lh
total 126M
-rw-rw-r-- 1 john john 126M Mar  5  2012 Puppy Linux 531.exe
john@john-desktop:~/Puppy_Linux_Installer$ find . -size 126M
./Puppy Linux 531.exe

john@john-desktop:~/test_examples$ find -size -1k

Find files owned by a particular user

If you need to find all files owned by a particular user, you can specify the "-user" option:

john@john-desktop:~/test_examples$ find . -user john . ./file3 ./file.txt ./file4.txt ./file2.txt ./file3.txt ./file1.txt ./file2

More information on the find command

Really, we have only scratched on the surface of the "find" command. There are many more options and flags that can be set. If you would like to find more information, don't forget to look at the "man pages" or issue find --help for more information..

Finding text within files with the "grep", "egrep" and "fgrep" commands

Grep is one of the most useful programs for searching for text within a single or multiple files using regular expressions. There are several varieties of the grep program.

fgrep: This is a stripped down version that does not allow regular expressions. Fgrep is restricted to character strings only. On the plus side, it is very fast.

egrep: This version does allow for regular expressions, however it is slower in operation and more memory intensive.

grep: This is Linux's default tool for text search. It fast and can handle regular expressions. Grep syntax requires at least a regular expression to search for. This is normally followed by a text file or files to be searched. If no file is specified, then grep will default to standard input. In addition to the regular expressions and file names there are various other options that can be passed from the command line. Some of the frequently used options:

grep options:

flag Description Result
-c Count Outputs the number of matching lines.
-i Ignore Case Ignores case of letters
-l List Only outputs the names of matching files
-n Number Includes the line numbers in the matching output
-r Recursive Searches in subdirectories too
-v Invert Outputs lines that do not match the regular expression
-f File File option for patterns that can be read from a file

grep Basic Examples

Search for the string "john" in the file "/etc/passwd"

john@john-desktop:~$ grep john /etc/passwd

Ignore the case of the string when searching using the "-i" option.

john@john-desktop:~$ grep -i JOHN /etc/passwd

Search recursively through files and directories looking for a given string. We then apply the "-i" option to ignore case.

john@john-desktop:~/test_examples$ ls -l
total 20
-rwxrwxrwx 1 john john   19 Jan 23 09:51 file1.txt
-rwxrwxrwx 1 john john   19 Jan 23 09:51 file2.txt
-rwxrwxrwx 1 john john   19 Jan 23 09:59 file3.txt
-rwxrwxrwx 1 john john   19 Jan 23 10:00 file4.txt
drwxrwxr-x 2 john john 4096 Jan 23 10:04 testdir
john@john-desktop:~/test_examples$ grep -r "some" .
./file2.txt:some text in file2
./file3.txt:somewhere in file3
./file1.txt:some text in file1
john@john-desktop:~/test_examples$ grep -ir "some" .
./testdir/file5.txt:Somewhere in file5
./file4.txt:Somewhere in file4
./file2.txt:some text in file2
./file3.txt:somewhere in file3
./file1.txt:some text in file1

Search for whole words only "-w" option. In this example, we are looking for the whole word "text" in file1.txt, file2.txt, file3.txt and file4.txt. Notice the use of the range on the filename "[1-4]".

john@john-desktop:~/test_examples$ grep -w "text" file[1-4].txt
file1.txt:some text in file1
file2.txt:some text in file2

Search for more than one whole word using "egrep".

john@john-desktop:~/test_examples$ egrep -iw "text|some" file[1-4].txt
file1.txt:some text in file1
file2.txt:some text in file2

Count the number of times a pattern has been matched using the "-c" count option
In this example, we ran the command twice. To show how the count was incremented after another line of text containing the specified word was appended.

john@john-desktop:~/test_examples$ grep -c "some" file1.txt
john@john-desktop:~/test_examples$ echo "some other line" >> file1.txt
john@john-desktop:~/test_examples$ grep -c "some" file1.txt 

This time we are using the "-n" option to add the line number that had the match

john@john-desktop:~/test_examples$ grep -n "some" file1.txt
1:some text in file1
2:some other line

List only matching file names. Use the "-l" option for listings.

john@john-desktop:~/test_examples$ grep -l 'some' *.txt .

grep and regular expressions

What are regular expressions?

Regular expressions are a powerful way to describe text to a command. Some of the most frequently used expressions are explained here. Some of which, you have already encountered with the find command.

In its simplest form "a" is a regular expression that matches the character "a".

"abc" matches the string "abc".

[a-c] matches exactly one character from "a" to "c".

a[bc]d matches either "abd" or "acd".

[A-Za-z] matches all upper and lowercase letters.

[^abc] matches all characters except for "a", "b" or "c". Note, in the shell we used [!abc].

the dot "." is the equivalent of the "?" in the shell. matches only one character; with the exception of the "\n" newline character.

"^" matches only at the beginning of a line.

"$" matches only at the end of the line.

"*" matches anything or nothing.

"\<" matches the beginning of a word.

"\>" matches the end of a word.

"|" Allows for more than one option. "red(car|hat|book)" would match "redcar", "redhat" or "redbook".

"?" The "?" is an optional expression, meaning it must occur at least once or not at all. "red(hat)?" matches either "red" or "redhat".