Advanced usage of 'find' (Re: Unix security automating script)

Martin Weitzel martin at mwtech.UUCP
Fri Mar 23 01:05:19 AEST 1990


In article <22817 at adm.BRL.MIL> konczal at mail-gw.ncsl.nist.gov (Joseph C. Konczal) writes:
>| echo ""
>| echo "* Directories that can be written to by everyone:"
>| ls -lR / | awk '/^d[rwx]......w[x-]/ { print }'
>| echo ""
>| echo "* Directories with search permissions for everyone:"
>| ls -lR / | awk '/^d[rwx]......w[x-]/ { print }'
>
>Replace the ls ... lines with:
>
>find / -type d -perm -0002 -print
>
>find / -type d -perm -0001 -print

Or replace the two 'find's by only one:

find / \( -type d -perm -0002 -o -type d -perm -0001 \) -print

Now 'find' has only to make one scan thrue the entire hierachy
of directories (which is a time consuming part of its work).

Most people who have a little experience with find know the above,
but often they seem not to know that 'find' can also do *different*
things during *one* single scan thrue the directories. (In fact, this
feature is not so obvious from RTFMing.)

Basically, a '-print', '-exec' or '-ok' is just like a condition
that can be *AND*-ed with other conditions. Evaluation of AND-ed
conditions is terminated as soon as the result turns out to be FALSE
(much like with && in C) so a '-print' is not evaluated, if the
condition(s) to the left evaluate to FALSE.

You also can do OR-ing several AND-ed conditions, which will make
more complex 'find' commands look as follows:

	find path \
		list-of-tests	print-or-exec-something \
	-o	list-of-tests	print-or-exec-something \
	-o	list-of-tests	print-or-exec-something \
	-o	list-of-tests	print-or-exec-something \
	-o	list-of-tests	print-or-exec-something \
	-o	print-or-exec-soemthing-for-the-default-case

These examples work, because OR-ed conditions *are* evaluated even if
the result allready turns out to be TRUE (*NOT* like with || in C!)

Normally you are only interested in the "side effects" of a '-print'
(printing the file name), but the utility of '-exec' extends beyond
its side effects: In contrary to '-print', which allways evaluates
to TRUE, '-exec' evaluates to the return status of the executed command.
So it is easy to test for conditions which are not among the "builtin"
tests of 'find'. You simply write a command (or shell procedure)
which tests for the special condition and let it return a TRUE
(zero) or FALSE (non-zero) exit status. Such a call to 'find' may
then look as follows:

	find path builtin-test -exec spc-test {} \; -print

It is recommendable to place such a special test *after* the builtins
(though it would also work swapped), because it forks and execs a new
process which could be avoided if the builtin test evaluates to FALSE.

Finally note that '-ok' is a little exceptional as it evaluates to
FALSE not only if the executed command returns a non-zero exit status,
but also if you don't respond "y" to its prompt. Look at the following
example:

	find path \
		first-builtin-test -ok command {} \; \
		second-builtin-test -exec other-command {} \; \
		-print

Try to figure out what it does, before you continue reading ...

Answer: If first-builtin-test evaluates to TRUE 'find' prompts you
with command and *if* you answer 'y' AND the commands exit status
is zero AND the second-builtin-test is TRUE, then other-command is
executed. Finally, if other-command too exits with status zero the
name of the file is printed. If you would not have answered 'y'
then neither the second-builtin-test would have been evaluated,
nor other-command would have a chance to execute.

Easy, not so?  :-)

I cross-post this to c.u.q and redirected followups there, but I leave
this article in c.u.w, because it is a followup to an article of this
group. I apologize if my tutorial about the advanced usage of 'find' is
vital knowledge among the readers of this group.

P.S.: The BUGS section of the 'find' command in the early UPM contained
the remark: "The syntax is painfull". IMHO, the author could well have
appended "but well thought".
-- 
Martin Weitzel, email: martin at mwtech.UUCP, voice: 49-(0)6151-6 56 83



More information about the Comp.unix.questions mailing list