Skip to main content
added 588 characters in body
Source Link
Stéphane Chazelas
  • 586.4k
  • 96
  • 1.1k
  • 1.7k

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 / in */* 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*/'*rc*' \ -o -path '*/*/class_project/*/*/pikachu/*/*/bambi/b‌​ambi.txt' \ \) -prune \   -o -print 

Turning to your command, 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/b‌​ambi.txt' \) -prune \   -o -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 / in */* 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/b‌​ambi.txt' \ \) -prune \ -o -print 
Address the unqouted globs plus show reduced example comand.
Source Link
B Layer
  • 5.3k
  • 1
  • 21
  • 35

YouThe first issue is that you have unquoted globs (*). All those paths should be surrounded with single quotes, e.g. '*/*/class_project/*/*/pikachu/*/*/bambi/b‌​ambi.txt'. This prevents the shell from expanding the wildcards before they get passed to find.

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 foo or bar in their names.

Some notes:

  • I'm being liberal with the -a/-o operators (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 find.
  • 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 -prune part.

For clarity let's rewrite this in a more common expression style:

((name=='*foo*' OR name=='*bar*') AND prune) OR (name==bar AND print) 

or even

if (name=='*foo*' OR name=='*bar*') prune else if (name==bar) print fi 

IfNow 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, 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/b‌​ambi.txttxt' \) -a -prune \) \ -o -print 

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 foo or bar in their names.

Some notes:

  • I'm being liberal with the -a/-o operators 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 find.
  • 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 -prune part.

For clarity let's rewrite this in a more common expression style:

((name=='*foo*' OR name=='*bar*') AND prune) OR (name==bar AND print) 

or even

if (name=='*foo*' OR name=='*bar*') prune else if (name==bar) print fi 

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/b‌​ambi.txt \) -a -prune \) \ -o -print 

The first issue is that you have unquoted globs (*). All those paths should be surrounded with single quotes, e.g. '*/*/class_project/*/*/pikachu/*/*/bambi/b‌​ambi.txt'. This prevents the shell from expanding the wildcards before they get passed to find.

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 foo or bar in their names.

Some notes:

  • 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 find.
  • 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 -prune part.

For clarity let's rewrite this in a more common expression style:

((name=='*foo*' OR name=='*bar*') AND prune) OR (name==bar AND print) 

or even

if (name=='*foo*' OR name=='*bar*') prune else if (name==bar) print fi 

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, 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/b‌​ambi.txt' \) -prune \ -o -print 
Show fixed version of OPs command.
Source Link
B Layer
  • 5.3k
  • 1
  • 21
  • 35

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 foo or bar in their names.

Some notes:

  • I'm being liberal with the -a/-o operators 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 find.
  • 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 -prune part.

For clarity let's rewrite this in a more common expression style:

((name=='*foo*' OR name=='*bar*') AND prune) OR (name==bar AND print) 

or even

if (name=='*foo*' OR name=='*bar*') prune else if (name==bar) print fi 

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/b‌​ambi.txt \) -a -prune \) \ -o -print 

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 foo or bar in their names.

Some notes:

  • I'm being liberal with the -a/-o operators 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 find.
  • 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 -prune part.

For clarity let's rewrite this in a more common expression style:

((name=='*foo*' OR name=='*bar*') AND prune) OR (name==bar AND print) 

or even

if (name=='*foo*' OR name=='*bar*') prune else if (name==bar) print fi 

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 foo or bar in their names.

Some notes:

  • I'm being liberal with the -a/-o operators 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 find.
  • 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 -prune part.

For clarity let's rewrite this in a more common expression style:

((name=='*foo*' OR name=='*bar*') AND prune) OR (name==bar AND print) 

or even

if (name=='*foo*' OR name=='*bar*') prune else if (name==bar) print fi 

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/b‌​ambi.txt \) -a -prune \) \ -o -print 
Further explanation/notes.
Source Link
B Layer
  • 5.3k
  • 1
  • 21
  • 35
Loading
Give examle in pseudo code for readability.
Source Link
B Layer
  • 5.3k
  • 1
  • 21
  • 35
Loading
Source Link
B Layer
  • 5.3k
  • 1
  • 21
  • 35
Loading