Finding Many Things with One Command (Unix Power Tools, 3rd Edition)
9.12. Finding Many Things with One Command
Running
find is fairly time consuming, and for good
reason: it has to read every inode in the directory tree that
it's searching. Therefore, combine as many things as
you can into a single find command. If
you're going to walk the entire tree, you may as
well accomplish as much as possible in the process.
Let's work from an
example. Assume that you want to write a command (eventually for
inclusion in a Chapter 27 shell script) that sets
file-access modes correctly. You want to give 771 access to all
directories, 600 access for all backup files
(*.BAK), 755 access for all shell scripts
(*.sh), and 644 access for all text files
(*.txt). You can do all this with one command:
$ find . \( -type d -a -exec chmod 771 {} \; \) -o \
\( -name "*.BAK" -a -exec chmod 600 {} \; \) -o \
\( -name "*.sh" -a -exec chmod 755 {} \; \) -o \
\( -name "*.txt" -a -exec chmod 644 {} \; \)
Why does this work? Remember that
-exec is really just another part of the
expression; it evaluates to true when the following command is
successful. It isn't an independent action that
somehow applies to the whole find operation.
Therefore, -exec can be mixed freely with
-type, -name, and so on.
However, there's another important trick here. Look
at the first chunk of the command -- the first statement, that is,
between the first pair of \( and
\). It says, "If this file is a
directory and the chmod command executes
successfully . . . " Wait. Why
doesn't the -exec execute a
chmod on every file in the directory to see
whether it's successful?
Logical expressions
are evaluated from left to right; in any chunk of the expression,
evaluation stops once it's clear what the outcome
is. Consider the logical expression
"`A AND B' is
true." If A is false, you know that the result of
"`A AND B' is
true" will also be false -- so
there's no need to look the rest of the statement,
B.
So in the previous multilayered expression, when
find is looking at a file, it checks whether the
file is a directory. If it is, -type d is true,
and find evaluates the
-exec (changing the file's
mode). If the file is not a directory, find
knows that the result of the entire statement will be false, so it
doesn't bother wasting time with the
-exec. find goes on to the
next chunk after the OR operator -- because,
logically, if one part of an OR expression isn't
true, the next part may be -- so evaluation of an OR . . . OR . .
. OR . . . expression has to continue until either one chunk is found
to be true, or they've all been found to be false.
In this case having the directory first is important, so that
directories named, for example, blah.BAK
don't lose their execute permissions.
Of course, there's no need for the
-execs to run the same kind of command. Some
could delete files, some could change modes, some could move them to
another directory, and so on.
One final point. Although understanding our multilayered
find expression was difficult, it really was no
different from a "garden variety"
command. Think about what the following command means:
% find . -name "*.c" -print
There are two operators:
-name (which evaluates to true if the
file's name ends in .c) and
-print (which is always true). The two operators
are ANDed together; we could stick a -a between
the two without changing the result at all. If
-name evaluates to false (i.e., if the
file's name doesn't end in
.c), find knows that the
entire expression will be false. So it doesn't
bother with -print. But if
-name evaluates to true,
find evaluates
-print -- which, as a side effect, prints the
name.
As we said in Section 9.6,
find's business is evaluating
expressions -- not locating files. Yes, find
certainly locates files; but that's really just a
side effect. For me, understanding this point was the conceptual
breakthrough that made find much more useful.
-- ML
9.11. Custom -exec Tests Applied9.13. Searching for Files by Type
Copyright © 2003 O'Reilly & Associates. All rights reserved.
Wyszukiwarka
Podobne podstrony:
ch09BW ch09ch09ch09CH09 (10)ch09ch09 (4)ch09ch09ch09ch09ch09ch09ch09ch09ch09więcej podobnych podstron