One of the commands that everyone should master is the find command. The first, and most obvious, use is find’s ability to locate old, big, or unused files, or files that you forgot where they are.
The other important characteristic is find’s ability to travel down subdirectories. If you wanted a recursive directory list, and ls doesn’t have this option, use find.
Normally the shell provides the argument list to a command. That is, Unix programs are frequently given file names and not directory names. Only a few programs can be given a directory name and march down the directory searching for subdirectories. The programs find, tar, du, and diff do this. The commands chmod, chgrp, rm, and cp will, but only if a -r or -R option is specified. In SunOS 4.1, ls supports the -R recursive option.
In general, most commands do not understand directory structures, and rely on the shell to expand meta-characters to directory names. That is, if you wanted to delete all object files ending with a “.o” in a group of directories, you could type
rm *.o */*.o */*/*.o
Not only is this tedious to type, it may not find all of the files you are searching for. The shell has certain blind spots. It will not match files in directories starting with a period. And, if any files match */*/*/*.o, they would not be deleted.
Another problem, although one that occurs less frequently in SunOS 4.0 and above, is typing the above, and getting the error “Arguments too long.” This means the number of arguments on the list was too large for the shell.
The answer to these problems is using find.
A simple example of find is using it to print the names of all of the files in the directory and all subdirectories. This is done with the simple command
find . -print
The first argument to find is a directory or file name. The arguments after the path names always start with a minus sign, and tells find what to do once it finds a file. These are the search options. In this case, the file name is printed. Any number of directories can be specified. You can use the tilde character supported by the C shell, as well as particular paths.
find ~ ~barnett /usr/local -print
And if you have a very slow day, you can type
find / -print
which will list every file on the system.
Excuse me. I just spoke an untruth. Every directory always contains the files . and ... Find could report these obvious files, but thankfully doesn’t.
“Using find with other commands’
Find sends its output to standard output. One way to use this is with the back quote command substitution:
ls -ld `find . -print`
The find command is executed, and its output replaces the back quoted string. Ls sees the output of find, and doesn’t even know find was used.
An alternate method uses the xargs command. Xargs and find work together beautifully. Xargs executes its arguments as commands, and reads standard input to specify arguments to that command. Xargs knows the maximum number or arguments each command line can handle, and does not exceed that limit. While the command
ls -ld `find / -print`
might generate an error when the command line is too large, the equivalent command using xargs will never generate that error:
find / -print | xargs ls -ld
Looking for files with particular names
You can look for particular files by using a regular expression with meta-characters as an argument to the -name option. The shell also understands these meta-characters, as it also understands regular expressions. It is necessary to quote these special characters, so they are passed to find unchanged. Either the back quote or single quotes can be used:
find . -name *.o -print
find . -name ‘*.o’ -print
find . -name ‘[a-zA-Z]*.o’ -print
The path of the file is not matched with the -name option, merely the name in the directory without the path leading to the file.
If you are only interested in files of a certain type, use the -type argument, followed by one of the following characters:
+—————————————————+
|Character Meaning |
+—————————————————+
|b Block special file (see mknode(8)) |
|c Character special file (see mknode(8)) |
|d Directory |
|f Plain file |
|p Named Pipe File |
|l Symbolic link |
|s Socket |
+—————————————————+
Unless you are a system administrator, the important types are directories, plain files, or symbolic links (i.e. types d, f, or l).
Using the -type option, another way to recursively list files is:
find . -type f -print | xargs ls -l
It can be difficult to keep track of all of the symbolic links in a directory. The next command will find all of the symbolic links in your home directory, and print the files your symbolic links point to.
find . -type l -print | xargs ls -ld | awk ‘{print $10}’
Find has several options that take a decimal integer. One such argument is -size. The number after this argument is the size of the files in disk blocks. Unfortunately, this is a very vague number. Earlier versions of Unix used disk blocks of 512 bytes. Newer versions allow larger block sizes, so a “block” of 512 bytes is misleading.
This confusion is aggravated when the command ls -s is used. The -s option lists the size of the file in blocks. If the command is “/usr/bin/ls,” the block size is 1024 bytes. If the command is “/usr/5bin/ls,” the block size is 512 bytes.
Let me confuse you some more. The following shows the two versions of ls:
% /usr/bin/ls -sl file
14 -rwxr-xr-x 1 barnett 13443 Jul 25 23:27 file
% /usr/5bin/ls -sl file
28 -rwxr-xr-x 1 barnett staff 13443 Jul 25 23:27 file
Can you guess what block size should be specified so that find prints this file? The correct command is:
find . -size 27 -print
because the actual size is between 26 and 16 blocks of 512 bytes each. As you can see, “ls -s” is not an accurate number for find. You can put a c after the number, and specify the size in bytes,
To search for files using a range of file sizes, a minus or plus sign can be specified before the number. The minus sign means “less than,” and the plus sign means “greater than.” This next example lists all files that are greater than 10,000 bytes, but less than 32,000 bytes:
find . -size +10000c -size -32000c -print
When more than one qualifier is given, both must be true.
If you want to find a file that is 7 days old, use the -mtime option:
find . -mtime 7 -print
An alternate way is to specify a range of times:
find . -mtime +6 -mtime -8 -print
Mtime is the last modified time of a file. You can also think of this as the creation time of the file, as Unix does not distinguish between creation and modification. If you want to look for files that have not been used, check the access time with the -atime argument. A command to list all files that have not be read in thirty days or more is
find . -type f -atime +30 -print
It is difficult to find directories that have not been accessed because the find command modifies the directory’s access time.
There is another time associated with each file, called the ctime, accessed with the -ctime option. This will have a more recent value if the owner, group, permission or number of links is changed, while the file itself does not. If you want to search for files with a specific number of links, use the -linksoption.
Searching for files by permission
Find can look for files with a specific permission. It uses an octal number for these permissions. The string rw-rw-r–, indicates you and members of your group have read and write permission, while the world has read only priviledge. The same permissions, when expressed as an octal number, is 664. To find all “*.o” files with the above permission, use:
find . -name *.o -perm 664 -print
If you want to see if you have any directories with world write permission, use:
find . -type d -perm 777 -print
This only matches the exact combination of permissions. If you wanted to find all directories with group write permission, there are several combinations that can match. You could list each combination, but find allows you to specify a pattern that can be bit-wise ANDed with the permissions of the file. Simply put a minus sign before the octal value. The group write permission bit is octal 20, so the following negative value:
find . -perm -20 -print
will match the following common permissions:
+————————-+
|Permission Octal value |
+————————-+
|rwxrwxrwx 777 |
|rwxrwxr-x 775 |
|rw-rw-rw- 666 |
|rw-rw-r– 664 |
|rw-rw—- 660 |
+————————-+
If you wanted to look for files that you can execute, (i.e. shell scripts or programs), you want to match the pattern “–x——,” by typing:
find . -perm -100 -print
When the -perm argument has a minus sign, all of the permission bits are examined, including the set user ID bits.


Posted in
Tags: 

