2

I have the following code in bash and I wonder on whether I can get rid of \+ and simply use +

   find "$fdir"                                \
      -type f -name "*.org" -o -name "*.texi"  \
      -exec head -n "$n" {} \+                 \
   | grep --color -e ^ -e '^==>.*' 
Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
Pietru
  • 371
  • 1
  • 14

1 Answers1

7

+ is not a special character in any shell and doesn't need quoted.

^ is special in a few shells though including the Thompson shell (first UNIX shell), Bourne shell, fish, rc, es, zsh with extendedglob. {} needs to be quoted in rc, and older versions of fish. *, (, ), > are special in most shells.

Note that not all head implementations accept more than one argument. The GNU implementation of head does and will print those ==> header lines but only when passed more than one argument or with the -v option.

Also note that AND (implied) has precedence over OR (-o) in find (see `find` with multiple `-name` and `-exec` executes only the last matches of `-name`), so:

find "$fdir"                                       \
   -type f '(' -name '*.org' -o -name '*.texi' ')' \
   -exec head -v -n "$n" '{}' +                    \
   | grep --color -e '^' -e '^==>.*'

(using '...' quoting in place of "..." or \ quoting for consistency only).

would work in Bourne-like, csh-like shells and fish. In rc/es, you'd need to remove the double quotes. In csh/tcsh, you'd replace "$fdir" with $fdir:q so it works even if $fdir contained newline characters.

The quotes around $fdir and $n are only needed in Bourne-like shells other than zsh and csh-like shells. " is not a quoting operator in rc/es. \ is not a quoting operator in rc either (though does do line continuation like in other shells).

See How to use a special character as a normal one in Unix shells? for what characters are special in which shell and how to escape / quote them.

Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
  • Why do you include `'('` and `')'`. – Pietru Jul 21 '21 at 18:55
  • @Pietru, because AND has precedence over OR, so `-type f -name '*.org' -o -name '*.texi' -exec...` is actually interpreted as `'(' -type f -name '*.org' ')' -o '(' -name '*.texi' -exec... ')'`. See [\`find\` with multiple \`-name\` and \`-exec\` executes only the last matches of \`-name\`](//unix.stackexchange.com/q/102191) – Stéphane Chazelas Jul 21 '21 at 18:59
  • Thank you Stéphane – Pietru Jul 21 '21 at 19:04
  • 1
    Shame the question in the title ("Does + need ...?") and the question in the body ("Can I get rid of...?") are logical opposites. I read "Does + need to be escaped?" and then the answer "Yes", and got confused. – jaimet May 18 '22 at 13:26
  • 2
    @jaimet, I've now removed the "yes" to avoid the possible confusion – Stéphane Chazelas May 18 '22 at 13:29