The first issue is that you have unquoted globs (
*). All those paths should be surrounded with single quotes, e.g.
'*/*/class_project/*/*/pikachu/*/*/bambi/bambi.txt'. This prevents the shell from expanding the wildcards before they get passed to
Next, you need the
-prune sub-expression to occur before the main search sub-expression. BTW, you can combine all the names into a compound expression with a single
-prune like this:
find \( \( -name '*foo*' -o -name '*bar*' \) -a -prune \) -o \( -name baz -a -print \)
This means I want to find files named
baz while excluding any files/directories containing
bar in their names.
- I'm being liberal with the
-a (AND) operator and the parentheses so there is no ambiguity.
- Parentheses, which act to change precedence just like with most other expression types, are escaped with
\ so they are not interpreted by the shell before being passed to
- I'm using two
-name tests but any other tests (e.g.
-path) can be in the first nested set of parentheses. Any file/dir matching any of the tests will be pruned and thus not applied to the next tests (in the last set of parens).
- It's a good idea to be explicit with the
-print action to distinguish it from the
For clarity let's rewrite this in a more common expression style:
((name=='*foo*' OR name=='*bar*') AND prune) OR (name==bar AND print)
if (name=='*foo*' OR name=='*bar*')
else if (name==bar)
Now given normal precedence rules and that the default boolean operator is
-a we can reduce the example down to:
find \( -name '*foo*' -o -name '*bar*' \) -prune -o -name baz -print
Turning to your command, the paths that
find constructs for the files it discovers will never end in
/ characters, so
-path '*/*/class_project/*/*/pikachu/*/*/*rc*/' could never possibly match. You'd need to drop that trailing
/ and possibly add a
-type d if you want to restrict to files of type directory.
Also note that
*/* as a pattern matches on any string that contains a
/, that also includes
foo/bar/baz. Here, your paths all start with
/students/projects/myname/ so the
*/* is redundant as we know already that that
/ will be there.
If I'm reading your intent correctly you don't have any tests for the second sub-expression, i.e. if a file doesn't get pruned you want to print it. So that leads to
find -L /students/projects/myname/ \
-name .aaa \
-o -path '*/class_project/*/*/pikachu/*/*/*rc*' \
-o -path '*/class_project/*/*/pikachu/*/*/bambi/bambi.txt' \
\) -prune \