原文:http://www.oracle.com/technology/pub/articles/calish-find.html
By Sheryl Calish
A quick introduction to the most powerful—as well as confusing—aspects of this ubiquitous command.
Published July 2008
The Linux findcommand is simultaneously one of the most useful and confounding of allLinux commands. It is difficult because its syntax varies from thestandard syntax of other Linux commands. It is powerful, however,because it allows you to find files by filename, by file type, by user,and even by time stamp. With the find command, not only areyou able to locate files with any combination of these attributes, butyou can also perform actions on the files it finds.
The purpose of this article is to simplify the task of learning and using the findcommand by giving you an overview of its purpose and potential. At thesame time, it will provide a basic tutorial and reference for some ofthe most powerful but confusing aspects of the find command.
[Note: The version of find used for this article is the GNU version, so some details may vary for other versions of find.]
To begin, let’s look at the basic structure of the find command:
find start_directory test options criteria_to_matchaction_to_perform_on_resultsIn the following command, find will start looking in the current directory, denoted by the “.”, for any file with the “java” extension in its name:
find . -name "*.java"
Here’s an abbreviated listing of what it found:
find . -name "*.java"./REGEXPvalidate/src/oracle/otnsamples/plsql/ConnectionManager.java./REGEXPvalidate/src/oracle/otnsamples/plsql/DBManager.java..
[Note:If you cut and paste from this article to run the find command, you mayneed to replace the double quotes (“”) using your own keyboard forproper results.]
The following command will do thesame thing. In either case, you need to escape the wildcard characterto be sure it passes to the find command and is not interpreted by theshell. So, put your search string in quotes, or precede it with abackslash:
find . -name \*.java
Althoughall arguments to find are optional, the search will begin by default inthe current directory if you do not specify where to begin searching.If you do not specify a test condition, an option, or a value to bematched your results will be either incomplete or indiscriminating.
Running the following three find commands will all yield the sameresults—a full listing of all files in the current directory and allsubdirectories including hidden files:
findfind .find . -print
This is similar torunning an ls command with the -la options. If you want the output ofthe above commands to contain the full pathnames, perhaps for a backup,you would need to specify the full path for the starting directory:
find /home/bluher -name \*.java/home/bluher/plsql/REGEXPvalidate/src/oracle/otnsamples/plsql/ConnectionManager.java/home/bluher/plsql/REGEXPvalidate/src/oracle/otnsamples/plsql/DBManager.java/...
Youcan also specify more than one starting directory in a search string.If run as a user with appropriate privileges, the following commandwill descend into the /usr, /home, and then /tmp directories to lookfor all jar files:
find /usr /home /tmp -name "*.jar"
Ifyou don’t have the appropriate permissions, however, you will generateerror messages as you begin to look through many system directories.The following is an example:
find: /tmp/orbit-root: Permission denied
You can avoid a cluttered output by appending your search string as follows:
find /usr /home /tmp -name "*.jar" 2>/dev/null
This sends all error messages to the null file, thereby providing cleaner output.
By default, find is case sensitive. For a case-insensitive find, substitute the -iname test for the -name test.
find downloads -iname "*.gif"downloads/.xvpics/Calendar05_enlarged.gifdownloads/lcmgcfexsmall.GIFYou can also search for files by types other than filename. Forinstance, you can find all the subdirectories in a directory with thefollowing command:
find . -type d
You can find all the symbolic links in your /usr directory with the following command:
find /usr -type l
Thiswill probably yield a list of more than 3,000 links. Either of thefollowing commands, run with root privileges, will yield a list oflinks in the /usr directory and the file to which it points:
# find /usr/bin -type l -name "z*" -exec ls -l {} \;lrwxrwxrwx 1 root root 8 Dec 12 23:17 /usr/bin/zsh -> /bin/zshlrwxrwxrwx 1 root root 5 Dec 12 23:17 /usr/bin/zless -> zmorelrwxrwxrwx 1 root root 9 Dec 12 23:17 /usr/bin/zcat -> /bin/zcat
find /usr/bin -type l -name "z*" -ls
Thesecond, shorter command, however, will yield a long file list withdirectory and inode information as well. We will discuss the use of the-exec and -ls actions later in this article.
Other filetypes that find can locate include
? b—block (buffered) special
? c—character (unbuffered) special
? p—named pipe (FIFO)
? s—socket
Using root as the starting point for a findcommand can slow down your system significantly. If you really must runsuch a command, you might run it during low-use time or overnight. Youcan redirect the output to a file using the following syntax:
find / -print > masterfilelist.out
Ifyou find you have erroneously entered a find command that producescopious unwanted output, just interrupt the command by pressing CTRL-C,which stops the most recently executed command.
On anenterprise network with multiple file systems, it is especially goodpractice to restrict the files that find looks for. Use as many of theoptions and tests as necessary to reduce the load on your system. Twoof the most useful options for this purpose are -xdev and -mount. Theynarrow the search by preventing find from descending into directorieson other file systems such as MS-DOS, CD-ROM, or AFS. This restrictsthe search to the same type of file system as the startdirectory.
Userson a dual boot system can play with these options if the mount commandis run. Assuming that a Windows partition is involved, you could mountit with something like the following command:
mount -t vfat /dev/sda1 /mnt/msdos
Theactual command that you use will depend on how your system is set up.You can verify that the partition was mounted by running df or byexecuting the following command:
find /mnt/msdos -name "*.txt" 2> /dev/null
Youshould see a long list of files on the MS Windows partition. Now runthe following command with either the -mount or -xdev option:
find / -name "*.txt" -mount 2> /dev/null
or
find / -name "*.txt" -xdev 2> /dev/null
Another possibility is to explicitly tell find which file system to look in using the -fstype test, as in this example:
find / -name "*.txt" -fstype vfat 2> /dev/null
The find command has several options that are used to search for files based on your system’s time stamps. These time stamps include
? mtime—the time that the contents of a file were last modified
? atime—the time that a file was read or accessed
? ctime—the time that a file’s status was changed
Whilethe meaning of mtime and atime is pretty self-evident, ctime requiresmore explanation. Because the inode maintains metadata on each file,the inode data will change if the metadata related to the file ischanged. This could be caused by a range of actions, including thecreation of a symbolic link to the file, changing the permissions on afile, or moving the file. Because the contents of the file are notbeing read or modified in these cases, themtime and atime will notchange, but the ctime will change.
Each of these time options needs to be used with a value n, which is specified as -n, n, or +n.
? -n returns less than n
? +n returns greater than n
? n, by itself,returns exactly n matches
Let’s look at some examples to make this clearer. The following command will find all the files modified within the last hour:
find . -mtime -1./plsql/FORALLSample./plsql/RegExpDNASample/plsql/RegExpSample
Running the same command with 1 instead of -1 finds all the files that were modified exactly one hour ago:
find . -mtime 1
Theabove command may not yield any results, because it asks for an exactmatch. The following command looks for the files that were modifiedmore than an hour ago:
find . -mtime +1Bydefault, -mtime, -atime, and -ctime refer to the last 24 hours. If,however, they are preceded by the daystart option, the 24-hour periodwill begin with the start of the current day. You can also look fortime stamps that have changed in less than an hour using mmin, amin,and cmin.
If you run the following immediately after logging into your account, you will find all files read less than 1 minute ago:
find . -amin -1./.bashrc/.bash_history./.xauthj5FCx1
It should be noted that locating a file with the find command itself changes that file’s access time as part of its metadata.
Youcan also find files that have been modified or accessed in comparisonto a specific file with the options -newer, -anewer, and –cnewer. Thisis similar to -mtime, -atime, and –ctime.
? -newer refers to files whose contents have been modified more recently
? -anewer refers to files that have been read more recently
? -cnewer refers to files whose status has changed more recently
To find all the files in your home directory that have been edited in some way since the last tar file, use this command:
find . -newer backup.tar.gz
The -size option finds files that meet the size criteria specified. To find all user files larger than 5MB, use
find / -size +5000000c 2> /dev/null/var/log/lastlog/var/log/cups/access_log.4/var/spool/mail/bluher
The“c” at the end reports our results in bytes. By default, find reportssize as the number of 512-byte blocks. We could also see the results asthe number of kilobytes if we replace the “c” with a “k” or as thenumber of two-byte words if we use a “w”.
The -sizeoption is frequently used to search for all zero-byte files and movethem to the /tmp/zerobyte folder. The following command does just that:
find test -type f -size 0 -exec mv {} /tmp/zerobyte \;
The-exec action allows find to perform any shell command on the files itencounters. You will see many more examples of its use later in thisarticle. The curly brackets allow each of the empty files to be moved.
The option -empty can also be used to find empty files:
find test -empty test/footest/test
Thefind command can be indispensable for monitoring the security of yoursystem. You can look for files with wide open permissions usingsymbolic or octal notation as follows:
find . -type f -perm a=rwx -exec ls -l {} \;
or
find . -type f -perm 777 -exec ls -l {} \;-rwxrwxrwx 1 bluher users 0 May 24 14:14 ./test.txt
Inthe above and the following commands in this section, we are using the-exec ls -l action so you can see the actual permissions of the filesreturned. The command will find files that are writable by both the“other” and the group:
find plsql -type f -perm -ug=rw -exec ls -l {} \; 2>/dev/null
or
find plsql -type f -perm -220 -exec ls -l {} \; 2>/dev/null-rw-rw-rw- 1 bluher users 4303 Jun 7 2004 plsql/FORALLSample/doc/otn_new.css-rw-rw-rw- 1 bluher users 10286 Jan 12 2005 plsql/FORALLSample/doc/readme.html-rw-rw-rw- 1 bluher users 22647 Jan 12 2005 plsql/FORALLSample/src/config.sql..This next command will find files that are writable by the user, the group, or both:
find plsql -type f -perm /ug=rw -exec ls -l {} \; 2>/dev/null, or,find plsql -type f -perm /220 -exec ls -l {} \; 2>/dev/null-rw-r--r-- 1 bluher users 21473 May 3 16:02 plsql/regexpvalidate.zip-rw-rw-rw- 1 bluher users 4303 Jun 7 2004 plsql/FORALLSample/doc/otn_new.css-rw-rw-rw- 1 bluher users 10286 Jan 12 2005 plsql/FORALLSample/doc/readme.html-rw-rw-rw- 1 bluher users 22647 Jan 12 2005 plsql/FORALLSample/src/config.sql
You may see the following command cited on the Web and in older manuals:
find . -perm +220 -exec ls -l {} \; 2> /dev/null
The + symbol does the same as the / symbol, although it is now deprecated in newer versions of GNU findutils.
To find all files on your system that are world writable, use the following command:
find / -wholename '/proc' -prune -o -type f -perm -0002 -exec ls -l {} \;-rw-rw-rw- 1 bluher users 4303 Jun 7 2004/home/bluher/plsql/FORALLSample/doc/otn_new.css-rw-rw-rw- 1 bluher users 10286 Jan 12 2005 /home/bluher/plsql/FORALLSample/doc/readme.html...
Thefourth permission will be discussed in just a bit, but the “2” in thelast field is the “other” field in the file permissions, also known asthe write bit. We used a dash before the permission mode of 0002 toindicate that we want to see files with the write permission set forothers, regardless of what other permissions are set.
Theabove command also introduces three new concepts. Using -wholenametests for the file pattern “/proc”, if that pattern is found, -prune prevents find from descending into that directory. The Boolean “-o”enables find to process the rest of the command for other directories.As there is an implicit and operator (-a) that is assumed between each expression, expressions following the andwill not be evaluated if the expression on the left evaluates to false;hence the need for the -o operator. The Boolean -not, !, is alsosupported by find, as is the use of parentheses to force precedence.
Systemadministrators frequently use find to search for regular files ofspecific users or groups using the name or ID of that user or group:
[root] $ find / -type f -user bluher -exec ls -ls {} \;
Here is a severely abbreviated sample of the output of such a command:
4 -rw-r--r-- 1 bluher users 48 May 1 03:09 /home/bluher/public_html/.directory4 -rw-r--r-- 1 bluher users 925 May 1 03:09 /home/bluher/.profile
You can also use find to look for a file by group:
[root] $ find / -type f -group users
find / -type d -gid 100
Thiscommand will yield a list of directories owned by group ID 100. To findthe appropriate uid or gid, you can run the more or cat command on the/etc/passwd or /etc/group file.
Beyond finding filesof specific known users and groups, you may also find it useful to lookfor files lacking either of these. This next command identifies filesthat do not have a listing in the /etc/passwd or /etc/group file:
find / -nouser -o -nogroup
Theabove command might not actually yield results on your system. It couldbe used, however, to identify files without a user or group, perhapsafter moving files around.
OK, now we can address that extra leading permission mentioned at the beginning of this section.
TheSGID and SUID are special access right flags that can be assigned tofiles and directories on a UNIX-based operating system. They are set toallow ordinary users on a computer system access to execute binaryexecutables with temporarily elevated privileges.
find / \( -perm -2000 -o -perm -4000 \) -ls167901 12 -rwsr-xr-x 1 root root 9340 Jun 16 2006 /usr/bin/rsh167334 12 -rwxr-sr-x 1 root tty 10532 May 4 2007 /usr/bin/wall
Inthe above command, you can see the use of escaped parentheses. You canalso see the differences in permissions. The first file has the SGIDpermission set, and the second file has the SUID permission set. Thefinal action in the above command works like find with the -exec ls-dils action.
Unlikemany commands in Linux, find does not require the -r or -R option inorder to descend into the subdirectories. It does this by default.However, you may want to limit this behavior at times. For that reason,the options -depth, -maxdepth, and -mindepth and the action -prune maycome in handy.
We have already seen how useful -prune can be, so let’s take a look at the -depth, -maxdepth, and -mindepth options.
The-maxdepth and -mindepth options allow you to specify how far down thedirectory tree you want find to search. If you want find to look injust one level of the directory, you would use the maxdepth option.
Youcan see the effects of -maxdepth by running the following command tolook for log files in the top three levels of the directory tree. Thiswill produce considerably less output than when run without it.
find / -maxdepth 3 -name "*log"
You can also tell find to look in directories at least three levels down the directory tree:
find / -mindepth 3 -name "*log"
The-depth option ensures that a directory is evaluated before its contentsare evaluated. The following command provides an example:
find -name "*test*" -depth./test/test./test./localbin/test./localbin/test_shell_var./localbin/test.txt./test2/test/test./test2/test./test2
Wehave looked at some of the more useful and somewhat obscure abilitiesof the find command, but there are additional tasks that find canperform. For instance, there are options that make find compatible with older UNIX versions and other operating systems andthat allow you to perform actions such as printing output to multiplefiles. After reading this article, you now have the background tounderstand the man page on find, and I encourage you to explore this powerful and useful tool.
聯(lián)系客服