- “Obviously” -exec …must be terminated with either a semicolon (;)
or a plus sign (+).  Semicolon is a special character in the shell
(or, at least, every shell I’ve ever used),
so, if it is to be used as part of thefindcommand,
it must be escaped or quoted (\;,";", or';').
- With - -exec … ;, the- {}string may appear
any number of times in the command, including zero,
or two or more, in any position. 
See this
for an example of why you might want to do- -execwithout using- {}. 
Having two or more appearances is useful principally
because, in (at least) some versions of- find,
the- {}doesn’t need to be a word by itself;
it can have other characters at the beginning or end; e.g.,
 - find . -type f -exec mv {} {}.bak ";"
 - With - -exec … +,
the- {}string must appear as the last argument before the- +. 
A command like
 - find . -name "*.bak" -exec mv {} backup_folder +
 - results in the enigmatic - find: missing argument to ‘-exec’error message.
 - 
- A workaround for this that’s specific to the - cpand- mvcommands is
 - find . -name "*.bak" -exec mv -t backup_folder {} +
 - or - find . -name "*.bak" -exec mv --target-directory=backup_folder {} +
 
 - The - {}must be a word by itself;
it cannot have other characters at the beginning or end. 
And, in (at least) some versions of- find,
you may not have more than one- {}.
 
- A sanity note: You can say - find . -name "*.sh" -type f -executable -exec {} optional args here ";"- to run each of your scripts.  But - find . -name "*.sh" -type f -executable -exec {} +- runs one of your scripts, with the names of all the others as parameters. 
This is similar to saying - ./*.sh
 - as a shell command,
except - finddoes not guarantee that it sorts its results,
so you aren’t guaranteed of running- aaa.sh(your alphabetically first- *.shfile)
as you would be with running- ./*.sh.
 
- An aspect of - findthat may not be perfectly clear to beginners is
that the command line is, effectively,
an executable statement in an arcane language. 
For example,
 - find . -name "*.sh" -type f -executable -print
 - means - for each file
    if the file’s name matches `*.sh` (i.e., if it ends with `.sh`)
    then
        if it is a plain file (i.e., not a directory)
        then
            if it is executable (i.e., the appropriate `---x--x--x` bit is set)
            then
                print the file’s name
            end if
        end if
    end if
end loop
 - or, simply, - for each file
    if the file’s name matches `*.sh`  AND  it is a plain file  AND  it is executable
    then
        print the file’s name
    end if
end loop
 - Some of the - -keywords are both an executable action and a test. 
In particular, this is true for- -exec … ;; for example,
 - find . -type f -exec grep -q cat {} ";" -print
 - translates to - for each file
    if it is a plain file (i.e., not a directory)
    then
        execute         grep -q cat filename
        if the process succeeds (i.e., exits with status 0)
        then
            print the file’s name
        end if
    end if
end loop- which will print the names of all files containing the string “- cat”. 
And, while this is something that- grepcan do by itself
(with the- -l(lower-case- L) option), it can be useful
to use it with- findto find files that contain a certain string
AND have a certain size AND are owned by a certain owner
AND were modified in a certain time range, ….
 - However, this does not work for - -exec … +. 
Since- -exec … +executes one command for multiple files,
it doesn’t make sense to use it as a logical condition
inside a- for each file …loop.
 
- The flip side of the above is that findgenerally exits
with an exit status of 0 unless you give it invalid arguments
or it encounters a directory that it can’t read. 
Even if a program that you execute fails
(exits with a non-zero exit status),findwill exit with an exit status of 0. 
Except if a program that you execute with-exec … +fails
(exits with a non-zero exit status),findwill exit with a non-zero exit status.