I'm trying to understand the syntax used with `find`, especially commands such as `find . -exec command {} ;`. Why must the semicolon be written as `;`? What would happen if I used a plain `;`, or left the terminator out entirely? The manual mentions protecting characters from expansion by the shell, but I'm not sure what "shell expansion" means in this context. How does the shell process these characters before `find` receives them?
2 Answers
A plain `;` is special syntax to the shell: it separates one command from the next. The shell processes it before starting `find`, so `find` never gets to see that semicolon. Writing `;` escapes it, which tells the shell to treat the semicolon as an ordinary character and pass it to `find` as an argument. In an `-exec` expression, `find` uses that semicolon to know where the command ends.
The shell parses and transforms your command line before launching a program. This includes things such as wildcard expansion (`*.txt` becoming a list of matching filenames), variable expansion (`$HOME`), command substitution, and interpreting syntax characters such as `;`, `|`, and `&`. Backslashes and quotes suppress that special treatment for the characters they protect. So `;` and `';'` both pass a literal semicolon to `find`, while a bare `;` is handled by the shell itself.

You can’t simply leave the terminator out because `find` needs it to know when the `-exec` command is complete. Escaping it is one way to pass it through; quoting it also works, for example with `';'`.