Unix Find Command Tutorial
http://www.softpanorama.org/Tools/find.shtml
Dr. Nikolai Bezroukov
Version 3.4
- Introduction
- Find logical expressions
- Finding files using name or path
- Finding files by age
- Using -exec option and xargs with find
- Finding SUID/SGUID files
- Finding World Writable, Abandoned and other Abnormal Files
- Finding Files based on size: largest, empty and within certain range
- Additional ways of controlling tree traversal
- Using find for backups
- Examples of Usage of Unix Find Command
- Summary
- Webliography
Introduction
See also Softpanorama find page Recommended Links Man pages Examples xargs tar cpio
Unix find is a pretty tricky but very useful utility that can often fool even experienced UNIX professionals with ten on more years of sysadmins work under the belt. It can enhance functionality of those Unix utilities that do not include tree traversal (BTW GNU grep has -r option for this purpose and can be used on its own to perform simple tree traversal tasks: grep -r "search string" /tmp.).
There are several versions of find with the main two being POSIX find used in Solaris, AIX, etc and GNU find used in linux. GNU find can be installed on Solaris and AIX and it is actually a strong recommendation as there are some differences; moreover gnu find have additional capabilities that are often useful.
The popularity of find is related to the fact that it can do more then a simple tree traversal available with option -r (or -R) in many Unix utilities. Traversal provided by find can have excluded directory tree branches, can select files or directories using regular expressions, can be limited to specific typed of filesystem, etc. Those capabilities are far superior to regular tree traversal the many Unix utilities provide. In this sense find is a real adherent to Unix component philosophy -- a useful enhancer of functionally of other utilities including both utilities that do not have capability to traverse the directory tree and those which have built-in simple recursive tree traversal
The idea behind find is extremely simple: this is a utility for searching files using the directory information and in this sense it is similar to ls. But it is more powerful then ls as it can provide " a ride" for other utilities and has an idiosyncratic mini-language for specifying queries, the language which probably outlived its usefulness, but nobody has courage to replace it with a standard scripting language.
For obscure historical reasons find mini-language is completely different from all other UNIX commands: it has full-word options rather than single-letter options. For example, instead of a typical Unix-style option -f to match filenames (like in tar -xvf mytar.tar) find uses option -name.
The first argument for find is the directory to search (search root). It important to understand that search root can consist of multiple directories, for example:
find /usr /bin /sbin /opt -name sar # here we exclude non-relevant directories
The list of directories to search can also be generated by script, for example:
find `gen_dir` -type f -size 0 -ls # script excludes some directories
After "search root" find expects so called "search expression". The first argument starting with "-" is considered to be a start of "search expression". Each component of search expression is aavluated to true or false and used to determine whether the file in question safisfy the expression or not. Some components like -exec have side effects.
To look across the /usr/local and /var/www/html directory trees for filenames that contain the pattern .htm, you can use the following command:
find /usr /var/html -name "*.htm*" -print
Please note that you need quotes for any regex (default is simple regex, but Perl style regex are availle with opetion ). Otherwise it will be evaluated immediately in the current context by shell.
It is simply impossible to remember all the details of this language unless you construct complex queries each day and that's why this page was created.
Along with this page it make sense to consult the list of typical (and not so typical) examples which can be found in in Examples page on this site as well as in the links listed in Webliography.
An excellent paper Advanced techniques for using the UNIX find command was written by Bill Zimmerly. I highly recommend to read it and then print for a reference. Several examples in this tutorial are borrowed from the article. An excellent paper Advanced techniques for using the UNIX find command was written by Bill Zimmerly. I highly recommend to read it and then print for a reference. Several examples in this tutorial are borrowed from the article.
The full find language is pretty complex and consist of several dozens of different predicates and options. There are two versions of this language: one implemented in POSIX find and the second implemented in GNU find which is a superset of POSIX find. That can make big difference in complex scripts. But for interactive use the differences is minor: only small subset of options is typically used on day-to-day basis by system administrators. Among them:
* -name True if pattern matches the current file name. Simple regex (shell patterns) may be used. it should be in quotes to prevent shell expansion. A backslash (\) is used as an escape character within the pattern. The pattern should be escaped or quoted. If you need to include parts of the path in the pattern in GNU find you should use predicate wholename If you need to use regular expressions you need to use predicates regextype and regex (only GNU find)
Use the -iname predicate (GNU find supports it) to run a case-insensitive search, rather than just -name. For example::
$ find . -follow -iname '*.htm' -print0 | xargs -i -0 mv '{}' ~/webhome
- Usage of -print0 is a simple insurance for the correct processing of files with spaces.
-fstype type True if the filesystem to which the file belongs is of type type. For example on Solaris mounted local filesystems have type ufs (Solaris 10 added zfs). For AIX local filesystem is jfs or jfs2 (journalled file system). If you want to traverse NFS filesystems you can use nfs (network file system). If you want to avoid traversing network and special filesystems you should use predicate local and in certain circumstances mount
"-atime/-ctime/-mtime" [+|-]n Each of those specifies selection of the files based on three Unix timestamps: the last time a files's "access time", "file status" and "modification time". n is time interval -- an integer with optional sign. It is measured in 24-hour periods (days) or minutes (GNU find only) counted from the current moment.
o n: If the integer n does not have sign this means exactly n 24-hour periods (days) ago, 0 means today. o +n: if it has plus sing, then it means "more then n 24-hour periods (days) ago", or older then n, o -n: if it has the minus sign, then it means less than n 24-hour periods (days) ago (-n), or younger then n. It's evident that -1, and 0 are the same and both means "today".
Note: If you use parameters with find command in scripts be careful when -mtime parameter is equal zero. Some (earlier) versions of GNU find incorrectly interpret the following expression:
find -mtime +0 -mtime -1
which should be equivalent to
find -mtime -1
- but does not produce any files
o o Examples
Find everything in your home directory modified in the last 24 hours:
find $HOME -mtime -1
Find everything in your home directory modified in the last seven 24-hour periods (days):
find $HOME -mtime -7
Find everything in your home directory that have NOT been modified in the last year:
find $HOME -mtime +365
To find html files that have been modified in the last seven 24-hour periods (days), I can use -mtime with the argument -7 (include the hyphen):
find . -mtime -7 -name "*.html" -print If you use the number 7 (without a hyphen), find will match only html files that were modified exactly seven 24-hour periods (days) ago:: find . -mtime 7 -name "*.html" -print + To find those html files that I haven't touched for at least seven 24-hour periods (days), I use +7:: find . -mtime +7 -name "*.html" -print
- -newer/-anewer/-cnewer baseline_file The time of modification, access time or creation time are compared with the same timestamp in the baseline file. If file is a symbolic link and the -H option or the -L option is in effect, the modification time of the file it points to is always used.
o -newer Modification time is compared with modification time of the baseline_file True if file was modified more recently than baseline file. o -anewer Access time is compared with access time of baseline_file . True if file was last accessed more recently than baseline file. o -cnewer Creation file is compared. For example: find everything in your home that has been modified more recently than "~joeuser/lastbatch.txt ":
find $HOME -newer ~joeuser/lastbatch.txt
-local True if the file system type is not a remote file system type. In Solaris those types are defined in the /etc/dfs/fstypes file. nfs is used as the default remote filesystem type if the /etc/dfs/fstypes file is not present. The -local option skips the hierarchy of non-local directories. You can also search without descending more then certain number of levels as explained later or exclude some directories from the search using
-mount Always true. Restricts the search to the file system containing the directory specified. Does not list mount points to other file systems.
-xdev Same as the -mount primary. Always evaluates to the value True. Prevents the find command from traversing a file system different from the one specified by the Path parameter.
-xattr True if the file has extended attributes.
-wholename simple-regex [GNU find only] . File name matches simple regular expression (often called shell patterns). In simple regular expressions the metacharacters '/' and '.' do not exist; so, for example, you can specify:
find . -wholename '/lib*'
which will print entries from directories /lib64 and /lib. To ignore the directories specified, use option -prune For example, to skip the directory /proc and all files and directories under it (which is important for linux as otherwise errors are produced you can something like this:
find . -wholename '/proc' -prune -o -name file_to_be_found
If you administer a lot of linux boxes it is better to create alias ff:
if [[ `uname` == "Linux" ]] ; do alias ff='find . -wholename '/proc' -prune -o -name ' else ff='find . -name ' # not GNU find does not support -wholename fi
Other useful options of the find command include:
1. -regex regex [GNU find only] File name matches regular expression. This is a match on the whole pathname not just a filename. The default regular expressions understood by find are Emacs Regular Expressions. This can be changed with the -regextype option. Currently implemented types are emacs (the default), posix-awk, posix-basic, posix-egrep and posix-extended. Predicate "-iregex" option provides the capability to ignore case. 2. -perm permissions Locates files with certain permission settings. Often used for finding world-writable files or SUID files. See below 3. -user Locates files that have specified ownership. Option -nouser locates files without ownership. For such files no user in /etc/passwd corresponds to file's numeric user ID (UID). such files are often created when tar of sip archive is transferred from other server on which the account probably exists under a different UID) 4. -group Locates files that are owned by specified group. Option -nogroup means that no group corresponds to file's numeric group ID (GID) of the file 5. -size Locates files with specified size. -size attribute lets you specify how big the files should be to match. You can specify your size in kilobytes and optionally also use + or - to specify size greater than or less than specified argument. For example:: find /home -name "*.txt" -size 100k find /home -name "*.txt" -size +100k find /home -name "*.txt" -size -100k
The first brings up files of exactly 100KB, the second only files greater than 100KB, and the last only files less than 100KB.
-ls list current file in ls -dils format on standard output.
- -type Locates a certain type of file. The most typical options for -type are as following::
- d -Directory
- f - File
- l - Link
For example to find a list of the directories use can use the -type specifier. Here's one example:
find . -type d -print
Part 2: Find logical expressions
Unix find uses its special "search expressions" language to define complex conditions to locate or ignore particular files and directories.
Expressions consist of multiple predicates (atomic expressions that evaluate to true or false connected by classic Boolean logic operations AND or OR or NOR.
a -- to have multiple conditions connected using logical AND. It is the default connector of individual search terms and explicit AND predicate is rarely used.
You can also specify as many conditions as you want to be connected with AND. For example, if you want to find the list of files that have been modified in the last 24 hours and have permission set to 777 (world-writable files), you would execute the following command:
find . -perm 777 -mtime 0 -print Which is the same as:: find . -perm 777 -a -mtime 0 -a -printo -- to have multiple conditions connected using logical OR. Usually in used in brackets to ensure proper order of evaluation. For example (-perm -4000 -o -perm -2000 )
! -- to negate a condition (logical NOT) . NOT should be specified with a backslash before exclamation point ( ! ). For example:
find . ! -name "*.gz" -exec gzip {} ;
By default search terms in find expressions are concatenated using AND predicate
The simplest "find search expression" is just one predicate. for example here is how to list all sub-trees of the current directory:
find . -print
As you can see in this case 'search expression consist of just one predicate (-print). Predicate -print always returns value TRUE, so each file will be printed. For example, if the system administrator want a list of .profile used by all users, the following command should be executed:
find / -name .profile -print
Here two predicates are connected by implicit AND operation. Another example of expression with two predicate expression is the expression the finds a list of all files (but not directories) modified in the last 24 hours:
find . -mtime 0 -type f
More complex search expression can contain sub-expressions in parentheses which makes "find search language" somewhat similar to regular algebraic expressions. As parentheses have a special meaning in Unix shell, they should be prefixed with the escape symbol "" or used inside single quotes as '(' and ')'. You cannot use single quotes around the entire expression as the find command interpret it as a single element of search expression. Typically ( expression ) -- "escaped parentheses" are used to define any composite condition. For example:
find / -type f \( -perm -4000 -o -perm -2000 \) -exec ls -l {} \;
This example shows that the same predicate can be used in find multiple times. Any predicate.
The same predicate can be used multiple times connected by AND or OR. In case of -name predicate such usage can simplify regular expressions
For example name can be used this way. In case of -name predicate such usage can simplify regular expressions. For example:
find / -type f \( -name "*.xls" -o -name "*.csv" \) -exec ls -l {} \;
is simpler then:
find / -regex ".*\.\(xls\|csv\)"
The find command checks the specified predicates and sub-expressions, going from left to right, once for each file or directory encountered. Here sub-expression ( -perm -4000 -o -perm -2000 ) is evaluated after the predicate "-type f" but before the predicate "-exec ls -l {} ;"
Part 4: Selecting files using their age
Find permits selection of files based on Unix mtime, ctime, and atime attributes. The standard unit is 24 hour periods (a day). GNU find also permits using minutes for the period, for example:
find / -mmin -10
Standard predicates that work with age of the file in file are : "-atime/-ctime/-mtime" [+|-]n and they use 24 hour periods (a day). Each compares with value provided with the Unix timestamps: the last time a files's "access time", "file change time, to be more exact, the inode change time" and "content modification time".
n is time interval -- an integer with optional sign. It is measured in 24-hour periods (days) or minutes counted from the current moment.
- n: If the integer n does not have sign this means exactly n 24-hour periods (days) ago, 0 means today.
- +n: if it has plus sing, then it means "more then n 24-hour periods (days) ago", or older then n,
- -n: if it has the minus sign, then it means less than n 24-hour periods (days) ago (-n), or younger then n. It's evident that -1 and 0 are the same and both means "today".
Examples:
* Find everything in your home directory modified in the last 24 hours::
find $HOME -mtime -1
* Find everything in your home directory modified in the last seven 24-hour periods (days)::
find $HOME -mtime -7
* Find everything in your home directory that have NOT been modified in the last year::
find $HOME -mtime +365
* To find html files that have been modified in the last seven 24-hour periods (days), I can use -mtime with the argument -7 (include the hyphen)::
find . -mtime -7 -name "*.html" -print
Note: If you use the number 7 (without a hyphen), find will match only html files that were modified exactly seven 24-hour periods (days) ago::
find . -mtime 7 -name "*.html" -print
* To find those html files that were not touched for at least seven 24-hour periods (days), use +7::
find . -mtime +7 -name "*.html" -print
Unix keeps track of three timestamps. Of them atime is the simplest the non-controversial: it stands for access time which is when the file was last read.
It is important to understand the precise meaning of ctime and mtime timestamps. The most common misconception here is to view ctime as file "creation time". It is actually "change time". Here are more formal explanations:
- ctime is the inode change time. When does the inode change, when you of course update a file, but also when you do things like changing the permissions of the file but not necessarily its contents. It would ne better to call this attribute change time as it indicates the last time a file’s metadata (inode) was changed. ctime changes when you change file's ownership or access permissions. As the man page for stat explains: “The field st_ctime is changed by writing or by setting inode information (i.e., owner, group, link count, mode, etc.).”
- mtime: is the "content modification time", so if you change the contents of the file, this timestamp is updated. Changes of name, ownership and permissions does not affect it
For a given file ctime and mtime can be different depending on if you just modified the inode or the contents of the file (which updates ctime as well). Commands like chown, chmod, and ln change only ctime. Touch command change only mtime. For example if you need to change the date to Jun 21, 2008 9AM to example.txt, then you can go (-t parameter in touch has format [[CC]YY]MMDDhhmm[.SS]):
touch -t 200907210900 example.txt
The second important thing to understand that unless -daystart option is used [Gnu find only], time in Unix find is measured in 24 hour periods (fractions are allowed in GNU find) from the current moment. Unless -daystart option is used [Gnu find only], time in Unix find is measured in 24 hour periods from the current moment
Those 24 hours periods are usually called "days" but the definition of "days" used in find is different from common usage (calendar days are typically understood as 24 hour periods starting at midnight). The "day" in "find language" is interpreted as "24 hour periods starting from the current time". Here is how working with time ranges described in GNU find documentation (Finding Files)
2.3.1 Age Ranges
These tests are mainly useful with ranges (‘+n’ and ‘-n’). — Test: -atime n — Test: -ctime n — Test: -mtime n
True if the file was last accessed (or its status changed, or it was modified) n*24 hours ago. The number of 24-hour periods since the file's timestamp is always rounded down; therefore 0 means “less than 24 hours ago”, 1 means “between 24 and 48 hours ago”, and so forth. Fractional values are supported but this only really makes sense for the case where ranges (‘+n’ and ‘-n’) are used.—Test: -amin n — Test: -cmin n — Test: -mmin n
True if the file was last accessed (or its status changed, or it was modified) n minutes ago. These tests provide finer granularity of measurement than ‘-atime’ et al., but rounding is done in a similar way (again, fractions are supported). For example, to list files in /u/bill that were last read from 2 to 6 minutes ago:
find /u/bill -amin +2 -amin -6—Option: -daystart
Measure times from the beginning of today rather than from 24 hours ago. So, to list the regular files in your home directory that were modified yesterday, do
find ~/ -daystart -type f -mtime 1The ‘-daystart’ option is unlike most other options in that it has an effect on the way that other tests are performed. The affected tests are ‘-amin’, ‘-cmin’, ‘-mmin’, ‘-atime’, ‘-ctime’ and ‘-mtime’. The ‘-daystart’ option only affects the behavior of any tests which appear after it on the command line.
Previous: Age Ranges, Up: Time 2.3.2 Comparing Timestamps — Test: -newerXY reference
Succeeds if timestamp ‘X’ of the file being considered is newer than timestamp ‘Y’ of the file reference. The letters ‘X’ and ‘Y’ can be any of the following letters:
- ‘a’
- Last-access time of reference
- ‘B’
- Birth time of reference (when this is not known, the test cannot succeed)
- ‘c’
- Last-change time of reference
- ‘m’
- Last-modification time of reference
‘t’
The reference argument is interpreted as a literal time, rather than the name of a file. See Date input formats, for a description of how the timestamp is understood. Tests of the form ‘-newerXt’ are valid but tests of the form ‘-newertY’ are not.
For example the test -newerac /tmp/foo succeeds for all files which have been accessed more recently than /tmp/foo was changed. Here ‘X’ is ‘a’ and ‘Y’ is ‘c’.
Not all files have a known birth time. If ‘Y’ is ‘b’ and the birth time of reference is not available, find exits with an explanatory error message. If ‘X’ is ‘b’ and we do not know the birth time the file currently being considered, the test simply fails (that is, it behaves like -false does).
Some operating systems (for example, most implementations of Unix) do not support file birth times. Some others, for example NetBSD-3.1, do. Even on operating systems which support file birth times, the information may not be available for specific files. For example, under NetBSD, file birth times are supported on UFS2 file systems, but not UFS1 file systems.
There are two ways to list files in /usr modified after February 1 of the current year. One uses ‘-newermt’:
find /usr -newermt "Feb 1"The other way of doing this works on the versions of find before 4.3.3:
touch -t 02010000 /tmp/stamp$$ find /usr -newer /tmp/stamp$$ rm -f /tmp/stamp$$—Test: -anewer file — Test: -cnewer file — Test: -newer file
True if the file was last accessed (or its status changed, or it was modified) more recently than file was modified. These tests are affected by ‘-follow’ only if ‘-follow’ comes before them on the command line. See Symbolic Links, for more information on ‘-follow’. As an example, to list any files modified since /bin/sh was last modified:
find . -newer /bin/sh—Test: -used n
True if the file was last accessed n days after its status was last changed. Useful for finding files that are not being used, and could perhaps be archived or removed to save disk space.
Expressions can be use to select files created or modified during contain intervals, for example files that are at least one week old (7 days) but less then 30 days old. You can combine the predicates like this:
find . -mtime +30 -a -mtime -7 -print0
Note: If you use parameters with find command in scripts be careful when -mtime parameter is equal zero ( -mtime +0 ). Earlier versions of GNU find incorrectly interpret the following expression:
ind -mtime +0 -mtime -1
which should be equivalent to:
ind -mtime -1
but does not produce any files...
Part 5: Using -exec option and xargs with find
Find is capable to perform various actions on the files or directories that are found. Among most commonly used actions are
print prints the names of the files on standard output (usually enabled by default); this list can be piped to the script for post processing. This is a default action and you can usually omit it.
o -print0 (GNU find only) tells find to use the null character (0) instead of whitespace as the output delimiter between pathnames found. This is a safer option if you files can contain blanks or other special character. It is recommended to use the -print0 argument to find if you use -exec command or xargs (the -0 argument is needed in xargs.).
exec command executes the specified command. This option is more suitable for executing relatively simple commands. For more complex things post processing of output is a safer option as you have some additional context to make the particular decision.
Find is able to execute one or more commands for each file it has found with the -exec option. Unfortunately, one cannot simply enter the command. You need to remember two syntactic tricks:
1. The command that you want to execute need to contain a special macro argument {}, which will be replaced by the matched filename on each invocation of -exec predicate.
2. You need to specify \; (or ';' ) at the end of the command. (If the \ is left out, the shell will interpret the ; as the end of the find command.)
In case {} macro parameter is the last item in the command then it should be a space between the {} and the \;. For example::
find . -type d -exec ls -ld {} \;
Here are several "global" chmod tricks based on find -exec capabilities:
find . -type f -exec chmod 500 {} ';'
This command will search in the current directory and all sub directories and change permissions of each file as specified.
find . -name "*rc.conf" -exec chmod o+r '{}' ;
find . -name "*rc.conf" -exec chmod o+r '{} ;'
This command will search in the current directory and all sub directories. All files named *rc.conf will be processed by the chmod -o+r command. The argument '{}' is a macro that expands to each found file. The ; argument indicates the exec argument has ended.
The end results of this command is all *rc.conf files have the other permissions set to read access (if the operator is the owner of the file).
Note: The -print option will print out the path of any file that is found with that name. In general -print is a default option.
The find command is commonly used to remove core files that are more than a few 24-hour periods (days) old. These core files are copies of the actual memory image of a running program when the program dies unexpectedly. They can be huge, so occasionally trimming them is wise:
find . -name core -ctime +4 -exec /bin/rm -f {} \;
For grep the /dev/null argument can by used to show the name of the file before the text that is found. Without it, only the text found is printed. An equivalent mechanism in GNU find is to use the "-H" or "--with-filename" option to grep:
find /tmp -exec grep "search string" '{}' /dev/null \; -print
An alternative to -exec option is piping output into xargs command which we will discuss in the next section. Feeding find output to pipes with xargs
One of the biggest limitations of the -exec option (or predicate with the side effect to be more correct) is that it can only run the specified command on one file at a time. The xargs command solves this problem by enabling users to run a single command on many files at one time. In general, it is much faster to run one command on many files, because this cuts down on the number of invocations of particular command/utility.
For example often one needs to find files containing a specific pattern in multiple directories one can use an exec option in find (please note that you should use the -l flag for grep so that grep specifies the matched filenames):
find . -type f -exec grep -li '/bin/ksh' {} \;
But there is more elegant and more Unix-like way of accomplishing the same task using xarg and pipes. You can use the xargs to read the output of find and build a pipelines that invokes grep. This way, grep is called only four or five times even though it might check through 200 or 300 files. By default, xargs always appends the list of filenames to the end of the specified command, so using it is as easy as can be:
find . -type f -print | xargs grep -li 'bin/ksh'
This gave the same output, but it was a lot faster. Also when grep is getting multiple filenames, it will automatically include the filename of any file that contains a match so option for grep -l is redundant:
find . -type f -print | xargs grep -i 'bin/ksh'
When used in combination, find, grep, and xargs are a potent team to help find files lost or misplaced anywhere in the UNIX file system. I encourage you to experiment further with these important commands to find ways they can help you work with UNIX. You can use time to find the difference in speed with -exec option vs xarg in the following way:
time find /usr/src -name "*.html" -exec grep -l foo '{}' ';' | wc -l
time find /usr/src -name "*.html" | xargs grep -l foo | wc -l
xargs works considerably faster. The difference becomes even greater when more complex commands are run and the list of files is longer.
find /mnt/zip -name "*prefs copy" -print | xargs rm
This is actually dangerous if you have a filename with spaces. If you add option -print0, you can avoid this danger:
find /mnt/zip -name "*prefs copy" -print0 | xargs rm
Two other useful options for xargs are the -p option, which makes xargs interactive, and the -n args option, which makes xargs run the specified command with only args number of arguments.
Some people wonder why there is a -p option. xargs runs the specified command on the filenames from its standard input, so interactive commands such as cp -i, mv -i, and rm -i don't work right.
The -p option solves that problem. In the preceding example, the -p option would have made the command safe because I could answer yes or no to each file. Thus, the command I typed was the following:
find /mnt/zip -name "*prefs copy" -print0 | xargs -p rm
Many users frequently ask why xargs should be used when shell command substitution archives the same results. Take a look at this example:
grep -l foo ´find /usr/src/linux -name "*.html"´
The drawback with commands such as this is that if the set of files returned by find is longer than the system's command-line length limit, the command will fail. The xargs approach gets around this problem because xargs runs the command as many times as is required, instead of just once.
Part 6: Finding SUID/SGUID files
Suid root refers to a special attribute called set user id. This attribute allows the program to do functions not normally allowed for owner of the file to perform.
Low level networking routines, controlling graphical display functions, changing passwords, and logging in are all examples of programs that rely on executing their functions as a user that is not restricted by standard file permissions. While many programs need this functionality, the program must be bug free in only allowing the user to do the function the program was designed for. Every SUID root program represents a potential security problem.
The first step in controlling SUID root programs is to have a baseline, the list of all SUID program in the system. This can be achieved quite easily by using find:
find / -type f -perm +6000 -exec ls -l {} \; > suid.list (note: this will find both set user id and set group id programs)
Above command is using GNU find and executes ls command. You cal use option -ls instead but output will be slightly different. Solaris POSIX find command different:
find / -type f \( -perm -4000 -o -perm -2000 \) -exec ls -l {} \;
This command will find all the SUID programs on a system and pipes the commands to a file called SUID.list. The next step in controlling SUID root programs is to analyze which programs should not be SUID root or can be removed without impeding system functionality. An obvious example of something that should not be SUID root is /usr/X11R6/bin/SuperProbe. This is a program merely used for testing purposes.
'chmod -s /usr/X11R6/bin/SuperProbe'
Other programs that are unneeded to be SUID root include anything in the svgalib hierarchy. This library itself is buggy and nothing that depends on it should be SUID root in a secure system.
Here is an example of minimized SUID.list though perhaps a little too overzealous. For example, the functionality that does not exist with this setup is ability to use ping and traceroute by a regular users and this is a typical security paranoia overkill. It can be compensated by controlling access to those program via sudo but this is road to nowhere.
But in any case minimization of the number of SUID program is task worth trying. It is excessive zeal that hurts...
Part 7: Finding World Writable, Abandoned and other Abnormal Files
Often system administrators need to detect "abnormal" files (e.g., world writable files, files with no valid owner and/or group, SetUID files, files with unusual permissions, sizes, names, or dates). WE already discusses a very important case of SUID/SGUID files. Now let's concentrate of other possibilities. Here is several simplified (usually you need to avoid traversing special filesystem and NFS mounts) but potentially useful examples:
* To find all world writable directories::
find / -perm -0002 -type d -print
* To find all world writable files::
find / -perm -0002 -type f -print
* Find both files and directories (exclude symbolic links which produce false positives)
find / -perm -2 ! -type l -ls
* Find files with messed UID or GID (possible as the result untarting files on a server with different structure of user accounts):
find / -nouser -o -nogroup -print
* Find broken symbolic links
$ find / -type l -print | perl -nle '-e || print';
Note: This command starts at the topmost directory (/) and lists all links (-type l -print) that the perl interpreter determines broken links (-nle '-e || print'). You can further pipe the output through xargs and use the rm -f {} if you want to delete such symbolic links.
* Clean out core dumps and temporary files
find . \( -name a.out -o -name '*.o' -o -name 'core' \) -exec rm {} \;
Those examples are pretty simplistic as in "real life" you need to be able to block traversing of NFS and other non-native filesystems and avoid getting to special memory-mapped filesystems like proc. Earlier versions of GNU find were allergic to proc filesystem. Here is one useful approach described in from Wayne Pollock's Unix-Linux find Command Tutorial
As a system administrator you can use find to locate suspicious files (e.g., world writable files, files with no valid owner and/or group, SetUID files, files with unusual permissions, sizes, names, or dates). Here's a final more complex example (which I save as a shell script):
- find / -noleaf -wholename '/proc' -prune
- -o -wholename '/sys' -prune -o -wholename '/dev' -prune -o -wholename '/windows-C-Drive' -prune -o -perm -2 ! -type l ! -type s ! ( -type d -perm -1000 ) -print
This says to search the whole system, skipping the directories /proc, /sys, /dev, and /windows-C-Drive (presumably a Windows partition on a dual-booted computer). The Gnu -noleaf option tells find not to assume all remaining mounted filesystems are Unix file systems (you might have a mounted CD for instance). The "-o" is the Boolean OR operator, and " !" is the Boolean NOT operator (applies to the following criteria).
Another and potentially simpler and faster approach is to use -fstype type predicate. It is true if the filesystem to which the file belongs is of type type. For example on Solaris mounted local filesystems have type ufs (Solaris 10 added zfs). For AIX local filesystem is jfs or jfs2 (journalled file system).
But sometimes the same server uses several types of local filesystems (for example ext3 and reisner). In this case you can use predicate OR and create expression that covers each used filesystem or use generic predicate local and in certain circumstances predicate mount.
Part 9: Using find for backups
The find command lets you copy the entire contents of a directory while preserving the permissions, times, and ownership of every file and subdirectory. Because find capabilities to specify complex criteria for files it can create a perfect list of files for cpio, tar, pax and another archiver to backup
Fortunately find has several options that are very useful for structuring the backup:
* -mount Don't descend directories on other filesystems. An alternate name for -xdev, for compatibility with some other versions of find.
* -fstype type File is on a filesystem of type type. The valid filesystem types vary among different versions of Unix; an incomplete list of filesystem types that are accepted on some version of Unix or another is: ufs, 4.2, 4.3, nfs, tmp, mfs, S51K, S52K. You can use -printf with the %F directive to see the types of your filesystems.
* -type c File is of type c::
o b block (buffered) special
o c character (unbuffered) special
o d directory
o p named pipe (FIFO)
o f regular file
o l symbolic link; this is never true if the -L option or the
-follow option is in effect, unless the symbolic link is
broken. If you want to search for symbolic links when -L
is in effect, use -xtype.
o s socket
o D door (Solaris)
The typical usage is to combine find and the cpio command, as the latter accepts the list of files via standard input. Tar can do this too with -T - option. Typically each mount point is backed up in a separate tar or cpio archive.
cd /usr
find /usr -mount fstype ext3 - | cpio -pdumv /backup/usr080124.cpi
or, using tar:
find /usr -mount fstype ext3 -print0 | tar -null -cvzf /backup/usr080124.tgz
It is also possible to do incremental backups using -newer option
find /usr -newer /backup/usr080124.tgz -mount fstype ext3 -print0 | tar -null -cvzf /backup/usr_delta080124.tgz
You can also try to avoid errors in backing up named pipes, devises, etc using more complex traversal expressions, for example
find / -mount -fstype ext3 ( -type f -or -type l ) > /tmp/root_list.txt
The problem here is with hard linked files. That that is problem of tar not find. The cpio command is a more sophisticated backup tool than tar. It is harder to use, but is capable of copying special files (such as devices and links) consistently, and will accept wildcard characters when listing the files to be archived.
On higher level you might benefit from exclusion of all files that are not changes in RPMs from which system was installed. This is the approach taken by backup built-in in YAST (it uses tar, not cpio). While tar cannot accept the list of files as standard input it has the -T option which can be used to specify the location of file with list of files to be tarred". Here is how this option is described in the manual:
Instead of giving the names of files or archive members on the command line, you can put the names into a file, and then use the ‘--files-from=file-of-names’ (‘-T file-of-names’) option to tar. Give the name of the file which contains the list of files to include as the argument to ‘--files-from’. In the list, the file names should be separated by newlines. You will frequently use this option when you have generated the list of files to archive with the find utility. ... ... ... In the file list given by ‘-T’ option, any file name beginning with ‘-’ character is considered a tar option and is processed accordingly.(14) For example, the common use of this feature is to change to another directory by specifying ‘-C’ option:: $ cat list -C/etc passwd hosts -C/lib libc.a $ tar -c -f foo.tar --files-from list
For example if we want to archive file that has size less then 1000 we can first create of list of such files using find and then use tar to created an archive.
find . -size -1K -print > /etc/small-files tar -cvzT /etc/small-files -f little.tgz
You can also compress the archive with gzip of the fly:
tar -zPvcf backup.tar.gz -T list_of_files_to_be_tarred_or_list_of_locations
You will want to use the ‘--label=archive-label’ (‘-V archive-label’) option to give the archive a volume label, so you can tell what this archive is even if the label falls off the tape, or anything like that.
Unless the file system you are dumping is guaranteed to fit on one volume, you might need to use the ‘--multi-volume’ (‘-M’) option.
Like find, tar has an option of that prevent it from crossing the filesystem (partition) boundaries: ‘--one-file-system’ option to prevent from crossing file system boundaries when storing (sub)directories.
It also has the ‘--incremental’ (‘-G’) option (see section Using tar to Perform Incremental Dumps).
Part 10: Examples of Usage of Unix Find Command See also Recommended Links Man pages Unix Find Tutorial
- Script with examples written by Viktor Chuyko
- Unix-Linux find command mini-tutorial
- Find tutorial from grymoire.com
- Advanced techniques for using the UNIX find command
- Some examples of using Unix find command.
- Find examples from www.wagoneers.com
- Examples from Sun manpage
Script with examples written by Viktor Chuyko
Script started on Fri Oct 1 10:31:16 1999 hills{501}vchuyk01: cat myfind #!/usr/bin/bash # EWORK8 # Script:myfind # Written by Viktor Chuyko # # This program demonstrates the features of find command # # This script is written in the bash scripting language # # #
It is great Mr. Wostner's idea to run 'date' command because the programs seaching the entire system with find command take incredibly long time to output the result. I could not get the output of myfind program inside script. It took a number of hours. I used another method to submit current assignment. Sorry about that.
echo date
echo echo "Next is listing of the files starting from home dir, that have size 50k or less and have extention html." find . ( -size 100 -o -size -100 ) -name '*.html'
-exec ls -l {} ; 2> /dev/null
echo echo "The following is the number of symbolic links starting from root:" find /students -type l -print 2> /dev/null |wc -l
echo echo "Below is listing of all directories starting from root that have sticky bit (t or T) set."
find / -type d -perm -1000 -exec ls -ld {} ; 2> /dev/null
echo echo "Here is creating "junk" directory." find ~ -type d -exec mkdir junk {} ; 2> /dev/null echo ls -ld ~/junk echo echo "I created the following empty files in junk directory:" echo find ~/junk -exec touch ~/junk/cart{1,2,3,4,5,6} {} ; 2> /dev/null
find ~/junk -name 'cart[1-6]' -exec ls -l {} ; 2> /dev/null echo echo "After renaming and removing some of the files from junk directory long listing of all the files in that directory looks like:" echo find ~/junk -name 'cart1' -exec mv {} ~/junk/A ; find ~/junk -name 'cart2' -exec mv {} ~/junk/B ; find ~/junk -name 'cart3' -exec mv {} ~/junk/C ;
#ls -l ~/junk
find ~/junk -name 'cart[4-6]' -exec rm {} ; find ~/junk -name "*" -exec ls -l {} ; #ls -l ~/junk
echo "Following is to say good bye." echo date hills{502}vchuyk01: myfind
Fri Oct 1 10:31:37 PDT 1999
Next is listing of the files starting from home dir, that have size 50k or less and have extention html. -rwxr-xr-x 1 vchuyk01 c73762 824 Sep 30 13:01 ./public_html/index.html -rw-r--r-- 1 vchuyk01 c73762 524 Sep 30 13:01 ./public_html/project_outline.html -rwxr--r-- 1 vchuyk01 c73762 4439 Sep 30 13:01 ./public_html/command.html -rw-r--r-- 1 vchuyk01 c73762 508 Sep 30 13:01 ./public_html/project.html -rw-r--r-- 1 vchuyk01 c73762 391 Sep 30 13:01 ./public_html/cut.html -rw-r--r-- 1 vchuyk01 c73762 335 Sep 30 13:01 ./public_html/paste.html -rw------- 1 vchuyk01 c73762 586 Sep 30 13:01 ./public_html/lynx_bookmarks.html -rw------- 1 vchuyk01 c73762 169 Sep 30 13:01 ./public_html/read.html -rw------- 1 vchuyk01 c32324 1004 Sep 30 13:01 ./lynx_bookmarks.html -rw------- 1 vchuyk01 c32324 304 Sep 30 13:01 ./project_outline.html
The following is the number of symbolic links starting from root:: 144
Below is listing of all directories starting from root that have sticky bit (t or T) set. d-wxrw--wt 3 3395 users 2048 Aug 10 1997 /opt/video/DVC_SDK/examples/xcam drwxrwxrwt 13 bin bin 571392 Sep 30 21:42 /tmp drwxrwxrwt 2 root root 2048 Sep 30 21:43 /var/spool/cron/tmp drwxrwsrwt 2 daemon daemon 2048 Sep 4 09:32 /var/spool/calendar drwxrwxrwt 6 root bin 2048 Sep 22 22:25 /var/opt/dce/rpc/local drwxr-xr-t 2 root sys 96 Sep 22 22:24 /var/opt/dce/rpc/local/00475 drwxr-xr-t 3 root root 96 Sep 22 22:25 /var/opt/dce/rpc/local/01191 drwxr-xr-t 2 root root 96 Sep 22 22:25 /var/opt/dce/rpc/local/01191/c-3 drwxrwxrwt 2 root sys 2048 Sep 22 22:25 /var/opt/dce/rpc/local/s-0 drwxrwxrwt 2 root sys 96 Sep 22 22:25 /var/opt/dce/rpc/local/s-3 drwxrwxrwt 2 root bin 96 May 30 1998 /var/opt/dce/security/creds drwxrwxrwt 2 root bin 96 Jun 10 1996 /var/opt/dce/svc drwxr-xr-t 2 sabensoh cisdept 1024 Aug 28 15:33 /pub/cis/cis110c/lab4 drwxr-xr-t 2 sabensoh cisdept 1024 Aug 28 15:32 /pub/cis/cis110c/lab6 drwxr-xr-t 2 sabensoh cisdept 1024 Aug 28 15:23 /pub/cis/cis110c/life1 drwxr-xr-t 2 sabensoh cisdept 1024 Aug 28 15:24 /pub/cis/cis110c/life2 drwxr-xr-t 2 sabensoh cisdept 1024 Aug 28 15:27 /pub/cis/cis110c/life3 drwxr-xr-t 2 sabensoh cisdept 1024 Aug 28 15:28 /pub/cis/cis110c/lab3
Here is creating "junk" directory.
drwx--S--- 2 vchuyk01 c73762 2048 Sep 30 21:37 /students/vchuyk01/junk
I created the following empty files in junk directory:
-rw------- 1 vchuyk01 c73762 0 Sep 30 21:43 /students/vchuyk01/junk/cart1 -rw------- 1 vchuyk01 c73762 0 Sep 30 21:43 /students/vchuyk01/junk/cart2 -rw------- 1 vchuyk01 c73762 0 Sep 30 21:43 /students/vchuyk01/junk/cart3 -rw------- 1 vchuyk01 c73762 0 Sep 30 21:43 /students/vchuyk01/junk/cart4 -rw------- 1 vchuyk01 c73762 0 Sep 30 21:43 /students/vchuyk01/junk/cart5 -rw------- 1 vchuyk01 c73762 0 Sep 30 21:43 /students/vchuyk01/junk/cart6
After renaming and removing some of the files from junk directory -rw------- 1 vchuyk01 c73762 0 Sep 30 21:43 /students/vchuyk01/junk/B -rw------- 1 vchuyk01 c73762 0 Sep 30 21:43 /students/vchuyk01/junk/C -rw------- 1 vchuyk01 c73762 0 Sep 30 21:43 /students/vchuyk01/junk/A Following is to say good bye.
hills{503}vchuyk01: exit exit
script done on Fri Oct 1 10:31:47 1999
Unix-Linux find command mini-tutorial Unix-Linux find command mini-tutorial
When specifying time with find options such as -mmin (minutes) or -mtime (24 hour periods, starting from now), you can specify a number "n" to mean exactly n, "-n" to mean less than n, and "+n" to mean more than n. 2 For example:
find . -mtime 0 # find files modified within the past 24 hours find . -mtime -1 # find files modified within the past 24 hours find . -mtime 1 # find files modified between 24 and 48 hours ago find . -mtime +1 # find files modified more than 48 hours ago find . -mmin +5 -mmin -10 # find files modifed between 6 and 9 minutes ago
The following displays non-hidden (no leading dot) files in the current directory only (no subdirectopries), with an arbitrary output format (see the man page for the dozens of possibilities with the -printf action):
find . -maxdepth 1 -name '[!.]*' -printf 'Name: %16f Size: %6sn'
As a system administrator you can use find to locate suspicious files (e.g., world writable files, files with no valid owner and/or group, SetUID files, files with unusual permissions, sizes, names, or dates). Here's a final more complex example (which I save as a shell script):
- find / -noleaf -wholename '/proc' -prune
- -o -wholename '/sys' -prune -o -wholename '/dev' -prune -o -wholename '/windows-C-Drive' -prune -o -perm -2 ! -type l ! -type s ! ( -type d -perm -1000 ) -print
This says to seach the whole system, skipping the directories /proc, /sys, /dev, and /windows-C-Drive (presumably a Windows partition on a dual-booted computer). The -noleaf option tells find to not assume all remaining mounted filesystems are Unix file systems (you might have a mounted CD for instance). The "-o" is the Boolean OR operator, and "!" is the Boolean NOT operator (applies to the following criteria). So this criteria says to locate files that are world writable ("-perm -2") and NOT symlinks ("! -type l") and NOT sockets ("! -type s") and NOT directories with the sticky (or text) bit set ("! ( -type d -perm -1000 )"). (Symlinks, sockets and directories with the sticky bit set are often world-writable and generally not suspicious.)
Find tutorial from grymoire.com Find tutorial from grymoire.com
Looking for files by type
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 -lIt 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}'Looking for files by sizes
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 fileCan you guess what block size should be specified so that find prints this file? The correct command is:
find . -size 27 -printbecause 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 -printWhen more than one qualifier is given, both must be true.
Searching for old files If you want to find a file that is 7 days old, use the -mtime option:
find . -mtime 7 -printAn alternate way is to specify a range of times:
find . -mtime +6 -mtime -8 -printMtime 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 -printIt 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 -printIf you want to see if you have any directories with world write permission, use:
find . -type d -perm 777 -printThis 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 -printwill 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 -printWhen the -perm argument has a minus sign, all of the permission bits are examined, including the set user ID bits.
Owners and groups
Often you need to look for a file that has certain permissions and belonging to a certain user or group. This is done with the -user and -group search options. To find all files that are set user ID to root, use:
find . -user root -perm -4000 -printTo find all files that are set group ID to staff, use:
find . -group staff -perm -2000 -printInstead of using a name or group in /etc/passwd or /etc/group, you can use a number:
find . -user 0 -perm -4000 -print find . -group 10 -perm -2000 -printOften, when a user leaves a site, their account is deleted, but their files are still on the computer. A system manager can use the -nouser or -nogroup to find files with an unknown user or group ID.
Find and commands
So far, after find has found a file, all it has done is printed the filename. It can do much more than that, but the syntax can get hairy. Using xargs saves you this mental effort, but it isn't always the best solution.
If you want a recursive listing, find's output can be piped into | xargs ls -l but it is more efficient to use the built in -ls option:
find . -lsThis is similar to the command:
find . -print | xargs ls -gildsYou could also use ls -R command, but that would be too easy.
Find and Cpio Find also understands cpio, and supports the -cpio and -ncpio commands:
find . -depth -cpio >/dev/rmt0 find . -depth -ncpio >/dev/rmt0which do the same as
find . -depth -print | cpio -oB >/dev/rmt0 find . -depth -print | cpio -ocB >/dev/rmt0Using Find to Execute Commands
I have already discussed how to use xargs to execute commands. Find can execute commands directly. The syntax is peculiar, which is one reasons I recommend xargs. The syntax of the -exec option allows you to execute any command, including another find command. If you consider that for a moment, you realize that find needs some way to distinguish the command it's executing from its own arguments. The obvious choice is to use the same end of command character as the shell (i.e. the semicolon). Since the shell normally uses the semicolon itself, it is necessary to "escape" the character with a backslash or quotes. There is one more special argument that find treats differently: {}. These two characters are used as the variable whose name is the file find found. Don't bother re-reading that last line. An example will clarify the usage. The following is a trivial case, and uses the -exec option to mimic the "-print' option.
find . -exec echo {} ;The C shell uses the characters { and }, but doesn't change {}, which is why it is not necessary to quote these characters. The semicolon must be quoted, however. Quotes can be used instead of a backslash:
find . -exec echo {} ';'as both will pass the semicolon past the shell to the find command. As I said before, find can even call find. If you wanted to list every symbolic link in every directory owned by group "staff" you could execute:
find `pwd` -group staff -exec find {} -type l -print ;To search for all files with group write permission, and remove the permission, you can use
find . -perm -20 -exec chmod g-w {} ;or
find . -perm -20 -print | xargs chmod g-wThe difference between -exec and xargs are subtle. The first one will execute the program once per file, while xargs can handle several files with each process. However, xargs may have problems with files that contain embedded spaces.
Occasionally people create a strange file that they can't delete. This could be caused by accidentally creating a file with a space or some control character in the name. Find and -exec can delete this file, while xargs could not. In this case, use ls -il to list the files and i-nodes, and use the -inum option with -exec to delete the file:
find . -inum 31246 -exec rm [] ';'If you wish, you can use -ok which does the same as -exec, except the program asks you first to confirm the action before executing the command. It is a good idea to be cautious when using find, because the program can make a mistake into a disaster. When in doubt, use echo as the command. Or send the output to a file and examine the file before using the file as input to xargs. This is how I discovered that find can only use one {} in the arguments to -exec. I wanted to rename some files using "-exec mv {} {}.orig" but I learned that I have to write a shell script that I told find to execute.
File comparisons Whenever I upgraded to a new version of Unix, one common problem was making sure I maintained all of the changes made to the standard release of Unix. Previously, I did a ls -lt in each directory, and then I examined the modification date. The files that were changed has an obviously newer date that the original programs. Even so, finding every change was tedious, as there were dozens of directories to be searched.
A better solution is to create a file as the first step in upgrading. I usually call this FirstFile. Find has a -newer option that tests each file and compares the modification date to the newer file. If you then wanted to list all files in /usr that need to be saved when the operating system is upgraded, use:
find /usr -newer /usr/FirstFile -printThis could then be used to create a tar or cpio file that would be restored after the upgrade.
Expressions Find allows complex expressions. To negate a test, put a ! before the option. Since the C shell interprets this command, it must be escaped. To find all files the same age or older than "FirstFile," use
find /usr ! -newer /FirstFile -printThe "and" function is performed by the -a option. This is not needed, as two or more options are ANDed automatically. The "or" function is done with the -o option. Parenthesis can be used to add precedence. These must also be escaped. If you wanted to print object and "a.out" files that are older than 7 days, use:
find . ( -name a.out -o -name *.o ) -printKeeping find from going too far
The most painful aspect of a large NFS environment is avoiding the access of files on NFS servers that are down. Find is particularly sensitive to this, because it is very easy to access dozens of machines with a single command. If find tries to explore a file server that happens to be down, it will time out. It is important to understand how to prevent find from going too far.
The important option in this case is -prune. This option confuses people because it is always true. It has a side-effect that is important. If the file being looked at is a directory, it will not travel down the directory. Here is an example that lists all files in a directory but does not look at any files in subdirectories under the top level:
find * -type f -print -o -type d -pruneThis will print all plain files and prune the search at all directories. To print files except for those in a Source Code Control Directories, use:
find . -print -o -name SCCS -pruneIf the -o option is excluded, the SCCS directory will be printed along with the other files.
Another useful combination is using -prune with -fstype or -xdev. Fstype tests for file system types, and expects an argument like nfs or 4.2. The later refers to the file system introduced in the 4.2 release of the Berkeley Software Distribution. To limit find to files only on a local disk or disks, use the clause -fstype 4.2 -prune or -o -fstype nfs -prune. If you needed to limit the search to one particular disk partition, use -xdev, The later is very useful if you want to help a congested disk partition, and wanted to look for all files greater than 40 blocks on the current disk partition;
find . -size -40 -xdev -print
Advanced techniques for using the UNIX find command Advanced techniques for using the UNIX find command by Bill Zimmerly
28 Mar 2006 (IBM DeveloperWorks) Clean out temporary files
You can use find to clean directories and subdirectories of the temporary files generated during normal use, thereby saving disk space. To do so, use the following command:
$ find . \( -name a.out -o -name '*.o' -o -name 'core' \) -exec rm {} \;File masks identifying the file types to be removed are located between the parentheses; each file mask is preceded by -name. This list can be extended to include any temporary file types you can come up with that need to be cleaned off the system. In the course of compiling and linking code, programmers and their tools generate file types like those shown in the example: a.out, *.o, and core. Other users have similar commonly generated temporary files and can edit the command accordingly, using file masks like *.tmp, *.junk, and so on. You might also find it useful to put the command into a script called clean, which you can execute whenever you need to clean a directory.
Copy a directory's contents
The find command lets you copy the entire contents of a directory while preserving the permissions, times, and ownership of every file and subdirectory. To do so, combine find and the cpio command, like this:
Listing 2. Combining the find and cpio command
$ cd /path/to/source/dir
$ find . | cpio -pdumv /path/to/destination/dir
The cpio command is a copy command designed to copy files into and out of a cpio or tar archive, automatically preserving permissions, times, and ownership of files and subdirectories.
List the first lines of text files
Some people use the first line of every text file as a heading or description of the file's contents. A report that lists the filenames and first line of each text file can make sifting through several hundred text files a lot easier. The following command lists the first line in every text file in your home directory in a report, ready to be examined at your leisure with the less command:
Listing 3. The less command
$ find $HOME/. -name *.txt -exec head -n 1 -v {} ; > report.txt
$ less < report.txt
Maintain LOG and TMP file storage spaces
To maintain LOG and TMP file storage space for applications that generate a lot of these files, you can put the following commands into a cron job that runs daily:
Listing 4. Maintaining LOG and TMP file storage spaces
$ find $LOGDIR -type d -mtime +0 -exec compress -r {} ;
$ find $LOGDIR -type d -mtime +5 -exec rm -f {} ;
The first command runs all the directories (-type d) found in the $LOGDIR directory wherein a file's data has been modified within the last 24 hours (-mtime +0) and compresses them (compress -r {}) to save disk space. The second command deletes them (rm -f {}) if they are more than a work-week old (-mtime +5), to increase the free space on the disk. In this way, the cron job automatically keeps the directories for a window of time that you specify.
Copy complex directory trees
If you want to copy complex directory trees from one machine to another while preserving copy permissions and the User ID and Group ID (UID and GID -- numbers used by the operating system to mark files for ownership purposes), and leaving user files alone, find and cpio once again come to the rescue:
Listing 5. Maintaining LOG and TMP file storage spaces
$ cd /source/directory
$ find . -depth -print | cpio -o -O /target/directory
Find links that point to nothing
To find links that point to nothing, use the perl interpreter with find, like this:
$ find / -type l -print | perl -nle '-e || print';This command starts at the topmost directory (/) and lists all links (-type l -print) that the perl interpreter determines point to nothing (-nle '-e || print') -- see the Resources section for more information regarding this tip from the Unix Guru Universe site. You can further pipe the output through the rm -f {} functionality if you want to delete the files. Perl is, of course, one of the many powerful interpretive language tools also found in most UNIX toolkits.
Some examples of using Unix find command Some examples of using Unix find command.
Introduction
Search for file with a specific name in a set of files (-name)
How to apply a unix command to a set of file (-exec).
How to apply a complex selection of files (-o and -a).
How to search for a string in a selection of files (-exec grep ...).
How to apply a complex selection of files (-o and -a).
find /usr/src -not ( -name ",v" -o -name ".,v" ) '{}' ; -print
- This command will search in the /usr/src directory and all sub directories. All files that are of the form ',v' and '.,v' are excluded. Important arguments to note are::
o -not means the negation of the expression that follows o ( means the start of a complex expression. o ) means the end of a complex expression. o -o means a logical or of a complex expression.
In this case the complex expression is all files like ',v' or '.,v'
The above example is shows how to select all file that are not part of the RCS system. This is important when you want go through a source tree and modify all the source files... but ... you don't want to affect the RCS version control files.
Find examples from www.wagoneers.com
find examples from www.wagoneers.com
sudo find / -type f -name *.jpg -exec cp {} . ;
find . -type f -size +10000 -exec ls -al {} ; find . -atime +1 -type f -exec mv {} TMP ; # mv files older then 1 day to dir TMP find . -name "-F" -exec rm {} ; # a script error created a file called -F find . -exec grep -i "vds admin" {} ; find . ! -name ".Z" -exec compress -f {} ; find . -type f ! -name ".Z" ! -name ".comment" -print | tee -a /tmp/list find . -name .ini find . -exec chmod 775 {} ; find . -user xuser1 -exec chown -R user2 {} ; find . -name ebtcom find . -name mkbook find . -exec grep PW0 {} ; find . -exec grep -i "pw0" {} ; find . -atime +6 find . -atime +6 -exec ll | more find . -atime +6 -exec ll | more ; find . -atime +6 -exec ll ; find . -atime +6 -exec ls ; find . -atime +30 -exec ls ; find . -atime +30 -exec ls ; | wc -l find . -name auth* find . -exec grep -i plotme10 {}; find . -exec grep -i plotme10 {} ; find . -ls -exec grep 'PLOT_FORMAT 22' {} ; find . -print -exec grep 'PLOT_FORMAT 22' {} ; find . -print -exec grep 'PLOT_FORMAT' {} ; find . -print -exec grep 'PLOT_FORMAT' {} ; find ./machbook -exec chown 184 {} ; find . ! -name '.Z' -exec compress {} ; find . ! -name ".Z" -exec compress -f {} ; find /raid/03c/ecn -xdev -type f -print find /raid/03c/ecn -xdev -path -type f -print find / -name .ssh* -print | tee -a ssh-stuff find . -name "font" find . -name hpmcad* find . -name fnt find . -name hp_mcad* -print find . -grep Pld {} ; find . -exec grep Pld {} ; find . -exec grep Pld {} ; find . -exec grep PENWIDTH {} ; | more find . -name config.pro find . -name config.pro find /raid -type d ".local_sd_customize" -print find /raid -type d -name ".local_sd_customize" -print find /raid -type d -name ".local_sd_customize" -ok cp /raid/04d/MCAD-apps/I_Custom/SD_custom/site_sd_customize/user_filer_project_dirs {} ; find /raid -type d -name ".local_sd_customize" -exec cp /raid/04d/MCAD-apps/I_Custom/SD_custom/site_sd_customize/user_filer_project_dirs {} ; find . -name xeroxrelease find . -exec grep xeroxrelease {} ; find . -name xeroxrelease find . -name xeroxrelease* -print 2>/dev/null find . -name "release" 2>/dev/null find / -name "xerox" 2>/dev/null find . -exec grep -i xeroxrelease {} ; find . -print -exec grep -i xeroxrelease {} ; find . -print -exec grep -i xeroxrelease {} ; > xeroxrel.lis find . -exec grep -i xeroxrel {} ; find . -print -exec grep -i xeroxrel {} ; find . -print -exec grep -i xeroxrel {} ; | more find /raid/03c/inwork -xdev -type f -print >> /raid/04d/user_scripts/prt_list.tmp find . -exec grep '31.53' {} ; find . -ls -exec grep "31/.53" {} ; > this.lis find . -print -exec grep "31/.53" {} ; > this.lis find . -print -exec grep 31.53 {} ; > this.lis find . -exec grep -i pen {} /; find . -exec grep -i pen {} ; find . -print -exec grep -i pen {} ; | more find . -exec grep -i pen {} ; find . -atime +6 -exec ll | more ; find . -atime +6 -exec ll ; find . -atime +6 -exec ls ; find . -atime +30 -exec ls ; find . -atime +30 -exec ls ; | wc -l find . ! -name '.Z' -exec compress -f {} ; find . -name 'cache' -depth -exec rm {} ; find . -name 'cache*' -depth -print | tee -a /tmp/cachefiles find . -name 'cache[0-9][0-9]*' -depth -print | tee -a /tmp/cachefiles find . -name 'hp_catfile' 'hp_catlock' -depth -print | tee -a /tmp/hp.cats find . -name 'hp_catfile' -name 'hp_catlock' -depth -print | tee -a /tmp/hp.cats find . -name 'hp_cat*' -depth -print | tee -a /tmp/hp.cats find . -name 'hp_cat[fl]*' -depth -print | tee -a /tmp/hp.cats find /raid -name 'hp_cat[fl]*' -depth -print find . ! -name '.Z' -exec compress -f {} ; find . -name '' -exec compress -f {} ; find . -xdev -name "wshp1*" -print find . -xdev -name "wagoneer*" -print find . -name "xcmd" -depth -print find /usr/contrib/src -name "xcmd" -depth -print find /raid -type d -name ".local_sd_customize" -exec ls {} ; find /raid -type d -name ".local_sd_customize"
-exec cp /raid/04d/MCAD-apps/I_Custom/SD_custom/site_sd_customize/user_filer_project_dirs {} ;
Examples from Sun manpage docs.sun.com man pages section 1 User Commands
Print all files with the given extension:
find . -name "*.c" -type f -print find /usr/local -name "*.html" -type f -printPrint all file that exceed a certain size and were modified long ago (to clear some space):
find / -size +1000 -mtime +30 -exec ls -l {} \; To report all files starting in the directories "/mydir1" and "/mydir2" larger than 2000 blocks (about 1000K) AND that have not been accessed in over 30 days, enter:: find /mydir1 /mydir2 -size +2000 -atime +30 -printRemoves unnecessary files that are older than two weeks old, but doesn't descend NFS mounted file systems while searching:
find / \( -name a.out -o -name core -o -name '#*#' \) -type f -atime +14 -exec rm -f {} \; -o -fstype nfs -pruneFix permissions for a group of files with given extension
find /usr/local -name "*.html" -type f -exec chmod 644 {} ;
find htdocs cgi-bin -name "*.cgi" -type f -exec chmod 755 {} ;
This command searches through the "htdocs" and "cgi-bin" directories for files that end with the extension ".cgi". When these files are found, their permission is changed to mode 755 (rwxr-xr-x). This example shows that the find command can easily search through multiple sub-directories (htdocs, cgi-bin) at one time.
SUID games (see above):
find / \( -perm -006 -o -perm -007 \) \( ! -type -l \) -ls # find all files that have wrong permission find / \( -nogroup -o -noname \) -ls * Does a difference on all file names that have SUID or SGID permissions against a pre-defined list of files find / \( -perm 2000 -o -perm 4000 \) -type f -ls | diff - suidfiles.refTo remove (with prompting) all files starting in the "/mydir" directory that have not been accessed in over 100 days, enter:
find /mydir -atime +100 -ok rm {} \;To show a long listing starting in "/mydir" of files not modified in over 20 days OR not accessed in over 40 days, enter:
find /mydir \(-mtime +20 -o -atime +40\) -exec ls -l {} \;To list and remove all regular files named "core" starting in the directory "/prog" that are larger than 500K, enter:
find /prog -type f -size +1000 -print -name core -exec rm {} \;How to apply a complex selection of files (-o and -a).
find /usr/src -not ( -name ",v" -o -name ".,v" ) '{}' ; -print
This command will search in the /usr/src directory and all sub directories. All files that are of the form ',v' and '.,v' are excluded. Important arguments to note are:
* -not( ! in Solaris) means the negation of the expression that follows * \( means the start of a complex expression. * \) means the end of a complex expression. * -o means a logical or of a complex expression. In this case the complex expression is all files like '*,v' or '.*,v'The above example is shows how to select all file that are not part of the RCS system. This is important when you want go through a source tree and modify all the source files... but ... you don't want to affect the RCS version control files.
How to search for a string in a selection of files (-exec grep ...).
find . -exec grep "www.athabasca" '{}' ; -print
This command will search in the current directory and all sub directories. All files that contain the string will have their path printed to standard output.
If you want to just find each file then pass it on for processing use the -q grep option. This finds the first occurrance of the search string. It then signals success to find and find continues searching for more files.
find . -exec grep -q "www.athabasca" '{}' ; -printThis command is very important for process a series of files that contain a specific string. You can then process each file appropriately. An example is find all html files with the string "www.athabascau.ca". You can then process the files with a sed script to change those occurrances of "www.athabascau.ca" with "intra.athabascau.ca".
Script with examples written by Viktor Chuyko
Script started on Fri Oct 1 10:31:16 1999 hills{501}vchuyk01: cat myfind #!/usr/bin/bash # EWORK8 # Script:myfind # Written by Viktor Chuyko # # This program demonstrates the features of find command # # This script is written in the bash scripting language # # #
It is great Mr. Wostner's idea to run 'date' command because the programs seaching the entire system with find command take incredibly long time to output the result. I could not get the output of myfind program inside script. It took a number of hours. I used another method to submit current assignment. Sorry about that.
echo date
echo echo "Next is listing of the files starting from home dir, that have size 50k or less and have extention html." find . ( -size 100 -o -size -100 ) -name '*.html'
-exec ls -l {} ; 2> /dev/null
echo echo "The following is the number of symbolic links starting from root:" find /students -type l -print 2> /dev/null |wc -l
echo echo "Below is listing of all directories starting from root that have sticky bit (t or T) set."
find / -type d -perm -1000 -exec ls -ld {} ; 2> /dev/null
echo echo "Here is creating "junk" directory." find ~ -type d -exec mkdir junk {} ; 2> /dev/null echo ls -ld ~/junk echo echo "I created the following empty files in junk directory:" echo find ~/junk -exec touch ~/junk/cart{1,2,3,4,5,6} {} ; 2> /dev/null
find ~/junk -name 'cart[1-6]' -exec ls -l {} ; 2> /dev/null echo echo "After renaming and removing some of the files from junk directory long listing of all the files in that directory looks like:" echo find ~/junk -name 'cart1' -exec mv {} ~/junk/A ; find ~/junk -name 'cart2' -exec mv {} ~/junk/B ; find ~/junk -name 'cart3' -exec mv {} ~/junk/C ;
#ls -l ~/junk
find ~/junk -name 'cart[4-6]' -exec rm {} ; find ~/junk -name "*" -exec ls -l {} ; #ls -l ~/junk
echo "Following is to say good bye." echo date hills{502}vchuyk01: myfind
Fri Oct 1 10:31:37 PDT 1999
Next is listing of the files starting from home dir, that have size 50k or less and have extention html. -rwxr-xr-x 1 vchuyk01 c73762 824 Sep 30 13:01 ./public_html/index.html -rw-r--r-- 1 vchuyk01 c73762 524 Sep 30 13:01 ./public_html/project_outline.html -rwxr--r-- 1 vchuyk01 c73762 4439 Sep 30 13:01 ./public_html/command.html -rw-r--r-- 1 vchuyk01 c73762 508 Sep 30 13:01 ./public_html/project.html -rw-r--r-- 1 vchuyk01 c73762 391 Sep 30 13:01 ./public_html/cut.html -rw-r--r-- 1 vchuyk01 c73762 335 Sep 30 13:01 ./public_html/paste.html -rw------- 1 vchuyk01 c73762 586 Sep 30 13:01 ./public_html/lynx_bookmarks.html -rw------- 1 vchuyk01 c73762 169 Sep 30 13:01 ./public_html/read.html -rw------- 1 vchuyk01 c32324 1004 Sep 30 13:01 ./lynx_bookmarks.html -rw------- 1 vchuyk01 c32324 304 Sep 30 13:01 ./project_outline.html
The following is the number of symbolic links starting from root:: 144
Below is listing of all directories starting from root that have sticky bit (t or T) set. d-wxrw--wt 3 3395 users 2048 Aug 10 1997 /opt/video/DVC_SDK/examples/xcam drwxrwxrwt 13 bin bin 571392 Sep 30 21:42 /tmp drwxrwxrwt 2 root root 2048 Sep 30 21:43 /var/spool/cron/tmp drwxrwsrwt 2 daemon daemon 2048 Sep 4 09:32 /var/spool/calendar drwxrwxrwt 6 root bin 2048 Sep 22 22:25 /var/opt/dce/rpc/local drwxr-xr-t 2 root sys 96 Sep 22 22:24 /var/opt/dce/rpc/local/00475 drwxr-xr-t 3 root root 96 Sep 22 22:25 /var/opt/dce/rpc/local/01191 drwxr-xr-t 2 root root 96 Sep 22 22:25 /var/opt/dce/rpc/local/01191/c-3 drwxrwxrwt 2 root sys 2048 Sep 22 22:25 /var/opt/dce/rpc/local/s-0 drwxrwxrwt 2 root sys 96 Sep 22 22:25 /var/opt/dce/rpc/local/s-3 drwxrwxrwt 2 root bin 96 May 30 1998 /var/opt/dce/security/creds drwxrwxrwt 2 root bin 96 Jun 10 1996 /var/opt/dce/svc drwxr-xr-t 2 sabensoh cisdept 1024 Aug 28 15:33 /pub/cis/cis110c/lab4 drwxr-xr-t 2 sabensoh cisdept 1024 Aug 28 15:32 /pub/cis/cis110c/lab6 drwxr-xr-t 2 sabensoh cisdept 1024 Aug 28 15:23 /pub/cis/cis110c/life1 drwxr-xr-t 2 sabensoh cisdept 1024 Aug 28 15:24 /pub/cis/cis110c/life2 drwxr-xr-t 2 sabensoh cisdept 1024 Aug 28 15:27 /pub/cis/cis110c/life3 drwxr-xr-t 2 sabensoh cisdept 1024 Aug 28 15:28 /pub/cis/cis110c/lab3
Here is creating "junk" directory.
drwx--S--- 2 vchuyk01 c73762 2048 Sep 30 21:37 /students/vchuyk01/junk
I created the following empty files in junk directory:
-rw------- 1 vchuyk01 c73762 0 Sep 30 21:43 /students/vchuyk01/junk/cart1 -rw------- 1 vchuyk01 c73762 0 Sep 30 21:43 /students/vchuyk01/junk/cart2 -rw------- 1 vchuyk01 c73762 0 Sep 30 21:43 /students/vchuyk01/junk/cart3 -rw------- 1 vchuyk01 c73762 0 Sep 30 21:43 /students/vchuyk01/junk/cart4 -rw------- 1 vchuyk01 c73762 0 Sep 30 21:43 /students/vchuyk01/junk/cart5 -rw------- 1 vchuyk01 c73762 0 Sep 30 21:43 /students/vchuyk01/junk/cart6
After renaming and removing some of the files from junk directory -rw------- 1 vchuyk01 c73762 0 Sep 30 21:43 /students/vchuyk01/junk/B -rw------- 1 vchuyk01 c73762 0 Sep 30 21:43 /students/vchuyk01/junk/C -rw------- 1 vchuyk01 c73762 0 Sep 30 21:43 /students/vchuyk01/junk/A Following is to say good bye.
hills{503}vchuyk01: exit exit
script done on Fri Oct 1 10:31:47 1999
O'Reilly - Safari Books Online - 0131018833 - HP-UX 11i System Administration Handbook and Toolkit, Second Edition
Finding Files of a Specific Type
You may want to perform a find operation to produce a list of files only and not include directories in the operation. The following find is similar to what we performed earlier, but this time it produces a list of files only. This is achieved by specifying that we are looking for type f for files:
# find /home -type f -printYou can search for a variety of different types such as f for a file as shown in the example, b for a block special file, l for a symbolic link, and so on.
Find Empty Files and Directories
A useful test when performing a find operation is to locate empty files. The following example searches for all empty files and directories on the system with the -empty operator that is available on some UNIX variants, including Linux. This is only a partial output because it's so long:
# find / -empty -printAll the files and directories listed as a result of this find operation are empty. The long listing of /auto shown as part of the example, confirms this fact. Keep in mind that -empty is not available on all UNIX variants.
Finding Files By Name, Size, and Both Name and Size
Let's perform a couple of independent finds and then combine the criteria of the finds. The finds in the following example are performed on a small, desktop system. This allows me to search the entire system for files meeting various criteria. You may be working on a much larger, more elaborate system, so use caution when searching the entire system for files. You may slow down other users for a long period of time, depending on the number of files on the system both locally and accessible over the network.
First, let's find for all files on the system ending in.c with the command below:
# find / -name *.c -printYou can see from this find that there are many files on the system ending in.c. I included only the beginning and end of this search because the entire output would be too long.
I also ran this command and piped the output to wc, which showed 1737 files on the system ending in.c, as shown in the following example:
# find / -name *.c | wc1737 1737 77044#
Now we can search for all files on the system greater than 500,000 characters in size with the find command below:
# find / -size +500000c -printI also ran this command and piped the output to wc, which showed 215 files on the system with a size greater than 500,000 characters, as shown in the following example:
# find / -size +500000c -print | wc215 215 6281#
Let's now combine the two commands and see how many of the files on the system ending in.c are also greater than 500,000 characters in size:
# find / -name *.c -size +500000c -print/usr/src/drivers/scsi/advansys.c #
Of the 1737 files on the system ending in.c and the 215 files greater than 500,000 characters in size, only one file, advansys.c, meets both criteria. There is an implied and in the previous find command. We could have explicitly specified an and; however, it is implied in the find command. The find did indeed result in files that end in.c and are greater than 500,000 characters. The upcoming find uses the or operator, which is not implied.
What if we wanted to find both files ending in.c and.o that are greater than 500000 characters in size? We could use the -o operator which would "or" the files ending in.c and.o. The following example shows this find operation:
find / -size +500000c ( -name *.c -o -name *.a ) -print find / -size +500000c ( -name *.c -o -name *.a ) -print | wc
# find / -size +500000c ( -name *.c -o -name *.a ) -print
The two file extensions for which we are searching are placed in parentheses. A backslash is required before the open and close parentheses because the parentheses have meaning to the shell and we want them to be used only to specify the precedence in our find command and not to be used by the shell. The result of this find shows that many files ending in.a and.c meet the criteria of greater than 500,000 characters.
Let's now pipe the output of this commnd to wc to see precisely the number of files ending in either.c or.o and have a size greater than 500,000 characters:
# find / -size +500000c \( -name *.c -o -name *.a \) -print | wc39 39 982#
Of the 39 files that meet the criteria, we know that 38 ended in.a because our earlier example showed that only one file ending in.c met the criteria.
Finding Files By Owner, Type, and Permissions
You can find objects on the system owned by particular users and groups. To find all of the objects owned by user "news" on the system, we would use the following command:
# find / -user news -printUsing the -user operator we can specify either the name of the user, in this case "news", or the user identification number. The following example shows performing the same find operation using the user identification number of "news," in this case "9," instead of the name "news":
# find / -user 9 -printThis find operation produced exactly the same results using the name "news" and the user idenfication number "9."
You can search for a variety of different types such as f for a file, as shown in the example, b for a block special file, l for a symbolic link, and so on. We could add type -d to find only directories belonging "news" as in the following command:
# find / -user news -type d -perm 775 -printThis is another example of using the implied and of find meaning that the find will print items that are both owned by "news" and are directories only.
Let's now add a specific permission for the directories to our implied and. We'll find only objects belonging to "news" that are directories with a permission of 775 in the following example:
# find / -user news -type d -perm 775 -printWe searched for directories belonging to "news" in which both the owner and those in the group have read-write-execute permission, and others have read-execute access. This is a common type of find operation for system administrators to perform - looking for files and directories belonging to a specific user and having specific permissions.
Part 11: Summary
Clearly, your use of the UNIX find command is limited only by your knowledge and creativity.
The find command has a lot of options, and to get the full power out of find, xargs, and grep, you need to experiment.
Among other things you can specify:
* where to search (pathname). Find understands multiple start points like in
find /usr /bin /sbin /opt -name sar
* Matching criteria, for example::
o name of the file(s) (-name). Can be a simple regex.
o -type what type of file to search for ( d -- directories, f -- files, l -- links)
o -atime n File was accessed "n" 24-hour periods (days) ago
o -mtime n File was modified "n" 24-hour periods (days) ago
o -size n File is "n" 512-byte blocks big
o -fstype typ Specifies filesystem type: 4.2 or nfs
o -name nam The filename is "nam"
o -user usr The file's owner is "usr"
o -group grp The file's group owner is "grp"
o -perm p The file's access mode is "p" (integer or symbolic expression)
* Actions
o -print display pathname (default)
o -exec how to process the files found ( {} expands to current found file )
* Combine matching criteria (predicated) into complex expressions using logical operations -o and -a (default binding) of predicates specified.
Selected Examples Option Meaning Example -atime n
-atime +n
-atime -n
| -size | True if file was accessed n 24-hour periods (days) ago (n), accessed more then n 24-hour periods (days) ago(+n) or less than n 24-hour periods (days) ago (-n)
|
-ctime n True if the file was created n 24-hour periods (days) ago. find . -ctime +30 -type f -exec rm {} ';' -exec command Execute command. find . -mtime -2 -type f -exec mv {} ../Spam_collector ; -mtime n True if file was modified n 24-hour periods (days) ago. find . -mtime -2 -type f -exec mv {} ../Spam_collector ; -name pattern True if filename matches pattern. -print Print names of files found. -type c True if file is of type c find . -mtime -2 -type f -exec mv {} ../Spam_collector ; -user name True if file is owned by user name.
Multiple options are joined by AND by default. OR may be specified with the -o flag and the use of grouped parentheses. For example, to match all files modified more than 90 24-hour periods (days) ago or accessed more than 30 24-hour periods (days) ago, use
( -mtime +90 -o -atime +30 )
NOT should be specified with a backslash before exclamation point. For example, to match all files ending in .txt except the file starting with "a-z", use:
\! -name "[a-z]*" -name "*.txt"
Unix Find Command Webliography News See also Tutorial Recommended Links Man pages Reference Unix Find Tutorial/Find logical expressions Finding SUID/SGUID files Selecting files using their age Traversal control Using find for backups Usage with cpio Usage with grep Usage with xarg Find and backup Examples Humor Etc
This is a webliography to my Find Tutorial.
Find is actually a pretty tricky utility that is different from any other Unix utility. Still it is one of the most important sysadmin tools. You need to put extra efforts to learn to use it correctly (and still without testing nothing is guaranteed in complex cases ;-).
Find is not only useful for finding files, it is also important for finding directories and can greatly simplify filesystem navigation. See Advanced Unix filesystem navigation and NCD clones for more details (in NCD clones find often is used for creation of the list of directories for the whole filesystem or some subtree and stored for future reference.
It uses non-standard regular expressions and have a very obscure mini-language to specify your queries. As one Softpanorama reader wrote: "find's syntax is NOT regular, does not recognize standard regex notation, and is arcane, irregular and infuriating."
That's why along with this page we created a mini-tutorial. I hope it can save you some time trying to make your complex find queries work (they almost never worked for me without debugging :-).
There are some interesting options in Posix find (as described in Solaris man page)
-fstype type True if the filesystem to which the file belongs is of type type. For example on Solaris mounted local filesystems have type ufs (Solaris 10 added zfs). For AIX local filesystem is jfs or jfs2 (journaled file system). If you want to traverse NFS filesystems you can use nfs (network file system).
"-atime/-ctime/-mtime" the last time a files's "access time", "file status" and "modification time", measured in days or minutes. The time can be compared to another file with "-newer/-anewer/-cnewer".
- o Example: find everything in your home directory modified in the last 24 hours::
- find $HOME -mtime 0
- o Example: find everything in your home directory modified in the last 7 days::
- find $HOME -mtime -7
- o Example: find everything in your home directory that have NOT been modified in the last year::
- find $HOME -mtime +365
- o Example: find everything in your home that has been modified more recently than "abc.txt"::
- find $HOME -newer ~joeuser/lastbatch.txt
-local True if the file system type is not a remote file system type as defined in the /etc/dfs/fstypes file. nfs is used as the default remote filesystem type if the /etc/dfs/fstypes file is not present. The -local option descends the hierarchy of non-local directories. See EXAMPLES for an example of how to search for local files without descending.
-mount Always true. Restricts the search to the file system containing the directory specified. Does not list mount points to other file systems.
-xdev Same as the -mount primary. Always evaluates to the value True. Prevents the find command from traversing a file system different from the one specified by the Path parameter.
-xattr True if the file has extended attributes.
Notes:
* This is a Spartan WHYFF (We Help You For Free) site written by people for whom English is not a native language. Some amount of grammar and spelling errors should be expected. * The site contain some broken links as it develops like a living tree... Please try to use Google, Open directory, etc. to find a replacement link (see HOWTO search the WEB for details). We would appreciate if you can mail us a correct link.
Copyright © 1996-2009 by Dr. Nikolai Bezroukov. www.softpanorama.org was created as a service to the UN Sustainable Development Networking Programme (SDNP) in the author free time. Submit comments This document is an industrial compilation designed and created exclusively for educational use and is placed under the copyright of the Open Content License(OPL). Site uses AdSense so you need to be aware of Google privacy policy. Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine.
Disclaimer:
* The statements, views and opinions presented on this web page are those of the author and are not endorsed by, nor do they necessarily reflect, the opinions of the author present and former employers, SDNP or any other organization the author may be associated with. * We do not warrant the correctness of the information provided or its fitness for any purpose * In no way this site is associated with or endorse cybersquatters using the term "softpanorama" with other main or country domains (e.g. softpanorama.com) with bad faith intent to profit from the goodwill belonging to someone else.
Created: May 16, 1997; Last modified: August 25, 2009
