|
Softpanorama |
May the source be with you, but remember the KISS principle ;-)
Softpanorama Search
|
Find is capable to perform various actions on the files or directories that are found. Among most commonly used actions are
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:
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.
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.
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:
Created: May 16, 1997; Last modified: August 25, 2009