I have the following directory structure (minimal example):
testdir
testdir/test2
testdir/test2/test2a
testdir/test2/test2a/test2aa
testdir/test1
testdir/test1/test1a
testdir/test1/test1a/test1aa
testdir/test1/test1b
testdir/test1/test1b/test1ba
I would like to find only folders in the depth layer directly below testdir
, excluding a certain folder name, here test1
. First, the output without excluding test1
:
user@xyz:/home/user $ find testdir/* -type d -prune
testdir/test1
testdir/test2
Now, I can exclude test1
:
user@xyz:/home/user $ find testdir/* -type d -prune ! -name test1
testdir/test2
However, by changing the order of the -prune
argument, subdirectories of test1
are returned:
user@xyz:/home/user $ find testdir/* -type d ! -name test1 -prune
testdir/test1/test1a
testdir/test1/test1b
testdir/test2
Why does the last command return the subdirectories test1a
and test1b
? I thought the order of the options would not matter, but apparently it does. As far as I understand (not sure about it), -prune
prevents find
from returning any paths below the patterns matched according to the find
options set. But the only match in the first layer below testdir
should be test2
. Could somebody clarify this for me?
Find -prune argument order affects output list
That's not especially surprising just on the face of it. The behavior of find
is sensitive in general to the relative order of predicates and actions.
The POSIX specifications for find
's behavior are a bit unspecific, but I think GNU find
's behavior is pretty typical in the relevant regards, even if that's not actually the find
you are using. Its manual page says:
GNU
find
searches the directory tree rooted at each given starting-point by evaluating the given expression from left to right [...] until the outcome is known (the left hand side is false for and operations, true for or), at which pointfind
moves on to the next file name.
(emphasis added).
Thus, if you put the -name
predicate before the -prune
action then the -prune
is performed only for paths that pass the -name
test, but if you put the -name
predicate after the -prune
then the -name
affects only whether paths are printed, not whether they are pruned.