1

I have a directory with the following files and a .git directory, e.g.

.
├── .git
│   ├── branches
│   ├── COMMIT_EDITMSG
│   ├── packed-refs
│   └── refs
├── readme.md
├── server_build.sh
└── tags

If I run GNU find command with the -prune test, find prints the directory which is prune'd:

% find . -name '.git' -prune
./.git

If add another OR option, then the directory which is pruned not longer appears in the output:

% find . -name '.git' -prune -o -name '*.md' -print
./readme.md

In this case, both -name '.git' and -name '*.md' tests must be returning true, it can't be possible that adding another OR test suddenly makes the -name '.git' -prune test untrue.
Is there some implicit switch being added to the first statement?
In other words is find turning

find . -name '.git' -prune

into

find . -name '.git' -prune -print

at run time? and the implicit -print is taken away when the next test when is added?
Why doesn't find print the -prune'd directory when another "-or" test is applied?

the_velour_fog
  • 11,840
  • 16
  • 64
  • 109
  • try `find . \( -name '.git' -prune -o -name '*.md' \) -print` also there is some discussion on this in `man find` just before `EXIT STATUS` – Sundeep Jul 19 '16 at 06:10
  • `find . -name '.git' -prune` prints `.git` because there is no other action. On the other hand, `find . -name '.git' -prune -o -name '*.md' -print` is actually equivalent to `find . \( -name '.git' -prune \) -o \( -name '*.md' \) -a -print `, and `-prune` no longer prints anything since there _is_ another action. – Satō Katsura Jul 19 '16 at 06:23
  • @SatoKatsura I thought `-prune` was an action, and therefore the implicit `-print` would not be used here. – the_velour_fog Jul 19 '16 at 06:26
  • 2
    From the manual: _If the expression contains no actions __other than -prune__, -print is performed on all files for which the expression is true._ – Satō Katsura Jul 19 '16 at 06:30
  • @SatoKatsura I think thats actually the answer – the_velour_fog Jul 19 '16 at 06:33
  • `-prune` is not a test, it's an action. – Henrik supports the community Jul 19 '16 at 06:42

1 Answers1

1
find . -name '.git' -prune

is the same as

find . -name '.git' -prune -print

so it prunes and then prints

find . -name '.git' -prune -o -name '*.md' -print

is the same as

find . \( -name '.git' -prune -true \) -o \( -name '*.md' -print \)

so it does first clause, if it does prune then it does true (prune returns true), and does not do right hand side of -o

These will always print

find . \( -name '.git' -prune -o -name '*.md' \) -print
find . -name '.git' -prune -print -o -name '*.md' -print
ctrl-alt-delor
  • 27,473
  • 9
  • 58
  • 102
  • ah I think I understand. So its possible to perform TWO actions on matching files. so ` find . -name '.git' -prune -print` is the same as ` find . -name '.git' -a -prune -a -print` .? and `-print` would not happen if prune returned false? – the_velour_fog Jul 19 '16 at 08:49
  • @the_velour_fog yes. – ctrl-alt-delor Jul 19 '16 at 09:09
  • thanks, although in your answer where you say `find . -name '.git' -prune -o -name '*.md' -print` is the same as `find . \( -name '.git' -prune -true \) -o \( -name '*.md' -print \)` and *and does not do right hand side of `-o`*. the right hand does get run - its the only statement that produces output. i.e. output is: `./readme.md` – the_velour_fog Jul 19 '16 at 09:33
  • 1
    Yes rhs should get evaluated when not `-name '.git'`. – ctrl-alt-delor Jul 21 '16 at 11:36