Most programs, including grep
don't treat parenthesis as arguments specially. If you did this:
grep "(" --include "*.texi" --exclude "*.org" ")"
grep
would treat the first (
as the pattern to search for, and the last )
as a filename.(*) Same as if they were foo
and bar
instead. So, you can't group options to grep
.
But here's the thing: -name
, -type
, -o
, and (
etc. aren't options to find
. It does take some options, namely -P
/-H
/-L
, which affect symlink processing, but these aren't options. Instead, they're part of the search expression, which is a thing specific to find
. (**)
Emphasis on expression there. When you give find
the expression ( -name *.texi -o -name *.org )
it's more like the C-like expression
( patternmatch(filename, "*.texi") || patternmatch(filename, "*.texi") )
than anything else. And find
evaluates that expression for each file it sees. If you had e.g. this instead:
( -name *.texi -o -name *.org ) -printf something
You'd need the parens, because without them:
-name *.texi -o -name *.org -printf something
would be the same as
-name *.texi -o -name *.org -a -printf something
because there's an implied and between atoms unless -o
is given, and then the expression would be
patternmatch(...) || patternmatch(...) && printf(...)
and the and operation binds tighter than the or operation, exactly in the same way it does in pretty much all programming languages, and in the same way multiplication binds tighter than addition. And find
can't know what you wanted, because it supports arbitrary expressions.(***) So, in this case, it wouldn't work like you want without the parens.
As others noted, the command you have doesn't need parens, since if there are no "actions" (-print
, -exec
etc.) in the find expression, it defaults to printing matching filenames, and also implicitly puts parenthesis around the expression.
So,
find "$fdir" -name "*.texi" -o -name "*.org"
acts like
find "$fdir" \( -name "*.texi" -o -name "*.org" \) -print
but if you explicitly put the -print
there, you also need to explicitly put the parenthesis to get the processing order right. See: `find` with multiple `-name` and `-exec` executes only the last matches of `-name`
Going back to grep
: grep
doesn't take parens, and doesn't need them, since it doesn't process expressions. It has no concept of nesting or operators like and and or in general. Instead, it has hard-coded behaviours. With --include
and --exclude
, I think it tries to fulfil both the include and exclude rules at the same time. (Or, at least one of the individual --include
rules and none of the individual --exclude
rules.) But with multiple search patterns, it's enough to match one, or another. Both of these are static rules: you can't give it a more complicated expression of which patterns should match.
(* GNU grep would take the middle ones as options, other implementations might take them as filenames too, as the non-option argument earlier stopped option processing. Also, you need to quote or escape the parens to prevent their special meaning to the shell; that's unrelated to what grep
does with them.)
(** In the same way that it's specific to grep
that the first non-option argument is a pattern, and only the rest are filenames, or that the last argument to mv
is a destination while the others are files to move, and it's specific to git
what it does with whatever arguments it takes. The tools do different things, so they have to use the command line arguments in different ways.)
(*** Someone once said that evaluating expressions is the main thing find
does. That is to say, it doesn't find filenames to print them, it goes through a tree of files to evaluate an expression on them. Printing and running external commands is just a side-effect.)
find
command should give you an error aboutsyntax error near unexpected token \
(', does it not? You need to escape parentheses from the shell in order for
findto see them, so that command should have been written as
find "$fdir" ( -name '.texi' -o -name '.org' )for the parentheses to work for
find`. – terdon Jul 26 '21 at 11:26\(
. – Pietru Jul 26 '21 at 11:35