dcsimg

Finding Stuff

Have you ever lost a file because you couldn't remember where you put it? Losing files is a common experience when learning a new operating system, and Linux users are hardly immune to it. The good news is that Linux provides the find command, which can help you banish the lost file experience from your daily routine. The better news is that find is extremely powerful and can help you do a lot more than just find lost files. Of course, a command this useful can take a while to master, so this month we're going to explore some of find's ins and outs.

Have you ever lost a file because you couldn’t remember where you put it? Losing files is a common experience when learning a new operating system, and Linux users are hardly immune to it. The good news is that Linux provides the find command, which can help you banish the lost file experience from your daily routine. The better news is that find is extremely powerful and can help you do a lot more than just find lost files. Of course, a command this useful can take a while to master, so this month we’re going to explore some of find’s ins and outs.

Finding Files by Name

A basic use of the find command is locating a file by its name. Of course, if you store every file in a single directory, being able to find a file by its name is not very impressive; the familiar ls command serves this purpose quite adequately.

The find command is helpful when you have a deeply nested collection of directories that contain other directories. For example, suppose you know that the file httpd.conf resides somewhere on your system but you don’t recall where. You can issue the following find command to locate the file:


find / -name httpd.conf

The syntax of the find command is admittedly a bit hairy, and we’ll dissect it in a minute. But the command we just issued would output a list of files having the name httpd.conf:


/etc/httpd/conf/httpd.conf

This file is the main configuration file of the Apache Web server. If you don’t have Apache installed on your system, the command wouldn’t find the file. In order to use the example commands given in this column, you’ll need to have the Apache Web server installed. If you haven’t installed it already, now is the time to do it. It is most likely included with whatever Linux distribution you’re using.




finding Without Error

Like other Linux commands, the find command is constrained by the file and directory access permissions available to the user. For instance, if you’re not permitted to search a directory (because you lack execute permission on that directory), the find command won’t search that directory. Therefore, if you run the find command as a user other than root, and begin a search at the root directory, you’ll probably see many lines of output stating “Permission denied.” You may not be able to find the result you’re interested in, owing to the avalanche of error messages.

To avoid this problem, you can redirect error messages to the bit bucket /dev/null by using the find command like this:


find / -name access_log 2>/dev/null

This causes error messages to be sent to the stderr stream, which is stream 2. Thus the phrase 2> redirects the error stream to the specified file, in this case /dev/ null. The special file /dev/null has the interesting property that output sent to it simply disappears. The file never fills up, and the output consumes no disk space. Redirecting the error messages this way causes them to vanish.


As promised, we are going to examine the arguments of the find command. The first argument specifies the directory in which to begin searching for the file. find will search all of the directories and subdirectories contained in the directory in which the search begins. In the example, this argument has the value /, which refers to the root directory. Because the root directory of a Linux system contains all other directories, this find command will search the entire system. If we knew that the file httpd.conf was somewhere under the /etc directory, we could issue the command:


find /etc -name httpd.conf

Because this command searches only under the /etc directory, it will execute somewhat more quickly than a command that specifies the root directory as the search directory.

The second argument of the find command is the option -name. This option specifies that the following argument gives the name of the file for which to search. In the previous example, we searched for the file named httpd.conf, but if we want to search for the file access_log, we could issue the command:


find / -name access_log

Finding Files by Partial Name

Suppose you know the file you seek has a name containing the phrase srm, but you don’t recall its entire name or the directory in which it resides. No problem — the find command lets you specify a search pattern rather than a complete file name. Here’s a simple example:


find /etc -name ‘*srm*’

This command finds all files residing in or below the /etc directory and having a name containing the characters srm. The asterisks allow characters to precede and follow the phrase srm so that the command will find files with names such as absrmyz.

If you know that the file’s name begins with srm, you can omit the leading asterisk, like this:


find /etc -name ‘srm*’

This command finds files with names such as srmyz but not files with names such as absrmyz or absrm. Similarly, omitting the second asterisk from the pattern would cause the command to find only files with names ending with the characters srm.

The single quotes that surround the pattern are important. If you omit them the command may malfunction because the shell may interpret and modify the pattern before passing it to the find command. There’s no getting around it; the rules that help you decide when and how (single quotes, double quotes or back quotes) to quote an argument are complex and beyond the scope of our article this month. However, until you’re confident in your understanding of these rules, simply enclose such patterns in single quotes. That way, the shell will leave them undisturbed.

Finding Files by Their Characteristics

In addition to letting you find files by name, the find command also lets you find files according to some of their characteristics (such as size). For example, to find all files having a size of exactly 1,500 bytes, you would issue the command:


find / -size 1500c

The c specifies that the size of the file is given in bytes.

Of course, you’re not often likely to know the exact size of a file you seek. The following command finds all files having a size larger than 10 million bytes:


find / -size +10000000c

The + indicates that the command should list files that have a size greater than that specified. If you specify a - instead, you can find files smaller than the specified size.

Table One summarizes other tests that you can include when issuing a find command. Meanwhile, Listing One shows some examples of issuing a find command with a test that you may find useful.





Listing One: Issuing the find Command


find / -amin -10    # find files accessed in last 10 minutes
find / -atime -2 # find files accessed in last 48 hours
find / -empty # find empty files and directories
find / -group cat # find files owned by group cat
find / -mmin -5 # find files modified in last 5 minutes
find / -mtime -1 # find files modified in last 24 hours
find / -nouser # find files owned by an invalid user
find / -user fred # find files owned by fred




Table One: find Command Tests







































TestDescription
-amin n File was last accessed n minutes ago.
-anewer file File was last accessed more recently than file was modified.
-atime n File was last accessed n*24 hours ago.
-cmin n File’s status was changed n minutes ago.
-cnewer file File’s status was last changed more recently than file was modified.
-ctime n File’s status was last changed n*24 hours ago.
-empty File is an empty file or a directory that contains no files or subdirectories.
-false Always false.
-fstype type File resides on a filesystem of the specified type; for example, ext2 .
-gid n File’s numeric group ID is n.
-group gname File belongs to group gname, which specifies a group name or ID.
-ilname pattern Like -lname , but ignores uppercase/lowercase distinctions.
-iname pattern Like -name , but ignores uppercase/lowercase distinctions.
-inum n File has inode number n.
-ipath pattern Like -path , but ignores uppercase/lowercase distinctions.
-iregex pattern Like -regex , but ignores uppercase/lowercase distinctions.
-links n File has n links.
-lname pattern File is a symbolic link with name matching pattern, which is a shell pattern.
-mmin n File’s data was last modified n minutes ago.
-mtime n File’s data was last modified n*24 hours ago.
-name pattern File name (excluding the names of directories in the path) matches pattern, which is a shell pattern. See -path .
-newer file File was modified more recently than file.
-nouser The file has a numeric user ID that does not correspond to any actual user.
-nogroup The file has a numeric group ID that does not correspond to any actual group ID.
-path pattern File name (including the names of directories in the path) matches pattern, which is a shell pattern. See -name .
-perm mode File’s permission bits have the value mode, which specifies an octal or symbolic value.
-perm -mode All the specified permissions of the file are set.
-perm +mode Any of the specified permissions of the file are set.
-regex pattern File name (including the names of directories in the path) matches pattern, which is a regular expression.
-size n[bckw] File uses n units of space. If c appears, the units are bytes; if k appears, the units are kilobytes; if w appears, the units are 2-byte words; otherwise, the units are 512-byte blocks.
-true Always true.
-type c File is of type c, which is a character special file. Files can be of several types, including:







b block special
c character special
d directory
f regular file
l symbolic link
p named pipe
s socket
-uid n File’s numeric user ID is n.
-used n File was last accessed n days after its status was last changed.
-user uname File is owned by username, which specifies a user name or numeric user ID.
-xtype c The same as -type unless the file is a symbolic link. In that case, if -follow is specified, the test is true if the file is a link to a file of type c; otherwise, the test is true if c is l.

Controlling the Operation of find

The find command also accepts several options that control its operation. The principal options are summarized in Table Two . Only a few of these are commonly used.




Table Two: find Command Options













Option
Description
-daystartMeasure elapsed time from the beginning of today, rather than from 24 hours ago. Used with tests such as -amin.
-depthUse a depth-first search process, which processes a directory’s contents before processing the directory itself.
-followFollow symbolic links; otherwise, symbolic links are ignored.
-helpPrint a command summary.
-maxdepth levelsDescend no more than levels directories below the directory specified in the argument list.
-mindepth levelsDescend at least levels directories below the directory specified in the argument list; that is, do not process the contents of directories above the specified depth.
-mountDon’t process directories on filesystems other than the filesystem that contains the path specified in the argument list. Same as -xdev.
-noleafDisables optimizations that can affect operation on MS-DOS and CD-ROM filesystems and other non-Unix filesystems.
-versionPrints the version number.
-xdevDon’t process directories on filesystems other than the filesystem that contains the path specified in the argument list. Same as -mount.

The -follow option causes the find command to follow symbolic links; unless you specify this option, the find command ignores symbolic links.

The -maxdepth option prevents the find command from descending more than a specified number of directory levels. For example, the following command that seeks a file named fred processes only the current directory (.) and its subdirectories:


find . -maxdepth 2 -name fred

If fred resides at ./sub1/fred, the command would locate the file; but if the file resides at ./sub1/sub2/fred, the command would not locate the file.

The -mount and -xdev options each have the same effect; they prevent the find command from searching filesystems other than the one that contains the specified search directory. By using either option, you can avoid searching a filesystem mounted as part of a directory tree that you do not want to search, thereby saving search time and possibly avoiding extraneous results. For example, suppose that the root directory contains several directories, including a filesystem mounted as /boot and another filesystem mounted as /usr. The search conducted by the command


find / -mount -name httpd.conf

would omit the /boot and /usr directories and any files and directories they contain.

Using Compound Conditions

The find command also lets you include multiple tests. You can specify that you want to list only files that satisfy all the tests or files that satisfy any of the tests. To do so, use the operators summarized in Table Three.




Table Three: find Command Operators










OptionDescription
(expr) Forces evaluation of the subexpression expr before evaluation of its context.
! expr True if expr is false.
-not expr True if expr is false.
expr1 expr2 True if both expr1 and expr2 are true.
expr1 -a expr2 True if both expr1 and expr2 are true.
expr1 -and expr2 True if both expr1 and expr2 are true.
expr1 -o expr2 True if either expr1 or expr2 is true.
expr1 -or expr2 True if either expr1 or expr2 is true.

For example, if you want to find files in the /tmp directory that are larger than 10 million bytes that have not been modified in the last 48 hours, you can issue the command:


find /tmp -size +10000000c -and -mtime +2

In this context, the tests (-size +10000000c -and -mtime +2) are referred to as expressions. As another example, this next command finds files that are owned by either fred or george:


find / -user fred -or -user george

If you want to reverse the results of a test, you can use the ! operator (sometimes referred to as the “not” operator). For example, to find files in the /tmp directory that are owned by someone other than fred, issue the command:


find /tmp ! -user fred

Manipulating Files

So far the example find commands have merely listed the locations of files we’ve found. However, the find command also allows you to display information about the found files in the form used by the familiar ls command. To do so, use the -ls option:


find / -name “httpd.conf” -ls

The output will resemble the following:


12063  34 -rw-r–r–  1 root  root 33545 Dec 30 15:36  /etc/httpd/conf/httpd.conf

Aside from allowing you to change the way the found files are displayed, the find command also lets you specify a command that it executes on each file that passes the tests you specify. This capability is associated with find’s -exec option. Simply follow this option with the command you want to execute. Here’s a simple example:


find. -name’a*’ -execrm\{\} \;

This command deletes files having names beginning with a from the current directory (.) and its subdirectories. The familiar rm command does the work. The peculiar string \{\} is replaced by the name of each file as it is found, and the \; marks the end of the command. So, the effect of the command is to execute rm x, where x takes as its value the name of each file that passes the tests specified in the find command.

Table Four (pg. 24) summarizes the action-related options of the find command.





Table Four: find Command Actions












OptionDescription
-exec command; Execute the command.
-fprint file Print the full name of the file to file.
-fprint0 file Print the full name of the file, followed by a null character, to file.
-fprintf file format Print format to file.
-ok command; Prompts the user and executes the command if the user responds with y or Y.
-print Print the full name of the file.
-print0 Print the full name of the file, followed by a null character.
-printf format Print format.
-prune Do not descend the current directory unless -depth is specified.
-ls List the file in the same format produced by the command ls -dils.

Conclusion

Now that you’ve got the find command at your side, losing files should become a thing of the past. And if you ever get bored, you can have all sorts of fun executing commands on files that you find. A word of warning — it can be dangerous to use the find command together with actions such as rm. You don’t want to start deleting things you might need. Never execute commands like that while logged in as root. You can accidentally cause all kinds of damage to your system. Meanwhile, until next month, have fun finding files!



Bill McCarty is an associate professor at Azusa Pacific University. He can be reached at bmccarty@apu.edu.

Comments are closed.