That's a great question about a common point of confusion in shell scripting! You're asking about $() versus backticks (`) for command substitution.
Both $(command) and `command` perform command substitution, meaning they execute a command and replace themselves with that command's standard output.
However, $(command) is generally the preferred and more modern syntax. Here's why and when to use one over the other:
Why $(...) is preferred:
-
Readability:
$(...)is much easier to read, especially when dealing with nested commands.- Good:
tar -cvf backup-$(date +%Y%m%d).tar $(find . -name "*.txt") - Harder to read:
tar -cvf backup-`date +%Y%m%d`.tar `find . -name "*.txt"`
The backticks can get lost among other quotes or characters, making it harder to discern where a command substitution begins and ends.
- Good:
-
Nesting:
$(...)allows for easy and natural nesting.- Example with nesting:
output=$(cat $(find . -name "file.txt")) - Nesting with backticks is tricky and requires escaping:
output=`cat \`find . -name "file.txt"\`` (Notice the\before the inner backticks). This quickly becomes cumbersome and error-prone.
- Example with nesting:
-
Clarity with other expanding characters: Backticks can sometimes be confused with single quotes.
$(...)makes it clear you're performing command substitution.
When you might still see or use backticks:
- Legacy Scripts: Many older shell scripts use backticks because
$(...)was introduced later (though it's been standard in POSIX shells for a long time, including Bash). You'll encounter them when working with existing codebases. - Simplicity: For very simple, non-nested commands, some people might still use backticks out of habit.
In summary:
- Always use
$(...)for new scripts or when modifying existing ones. It's more readable, easier to nest, and less prone to errors. - Be aware of backticks (
`) because you will see them in older scripts, but aim to use$(...)yourself.
In your current step, POSITION=$(expr index "$STRING" "$CHAR") uses the recommended $(...) syntax for good reason – it clearly captures the output of the expr command.
Does that explanation clarify the difference for you?