In shell commands, quotes serve as metacharacter control and pattern protection. These three forms are all valid for simple patterns:
grep hello file.txt
grep 'hello' file.txt
grep "hello" file.txt
The differences emerge when:
# Contains spaces - requires quotes
grep 'hello world' file.txt
# Contains special characters - requires escaping
grep 'price: \$100' file.txt
grep "price: \\$100" file.txt
# Variable expansion needed
NAME="John"
grep "$NAME" file.txt # Double quotes allow expansion
grep '$NAME' file.txt # Single quotes treat literally
Consider these scenarios with special regex characters:
# Searching for literal dot (.)
grep 'example\.com' file.txt # Correct
grep example.com file.txt # Matches "exampleXcom" too
# Searching for asterisk (*)
grep '\*' file.txt # Finds literal *
grep '*' file.txt # Shell expansion may occur
For reliable scripting:
# Always quote patterns containing:
# - Spaces
# - Special characters (.*?+[] etc.)
# - Variables needing expansion
# Recommended form for static patterns
grep 'fixed-pattern' file.txt
# When variables are involved
grep "$dynamic_pattern" file.txt
Different shells handle expansion differently:
# Bash/zsh vs older sh differences
pattern="*.txt"
grep "$pattern" file # Safe expansion
grep $pattern file # Potential glob expansion
Remember that grep itself sees the final expanded pattern after shell processing.
When searching for simple literal strings like "hello", all these grep forms work equivalently:
grep hello file.txt
grep 'hello' file.txt
grep "hello" file.txt
The shell processes these commands before grep sees them, and for plain strings without special characters, the quotes are effectively removed during this processing.
Quoting becomes crucial when your search pattern contains:
- Shell metacharacters (spaces, *, ?, $ etc.)
- Regular expression special characters
- Variables that need expansion
Single quotes prevent all shell interpretation:
grep 'hello$' file.txt # Searches for literal "hello$"
grep 'hello.*world' file.txt # Regex metacharacters preserved
Double quotes allow variable expansion and some escaping:
name="John"
grep "Hello $name" file.txt # Variable gets expanded
grep "Price: \$100" file.txt # Escaped dollar sign
Without quotes, the shell performs word splitting and globbing:
grep hello world file.txt # Searches for "hello" in files "world" and "file.txt"
grep hello * # Searches all files in directory
For patterns containing brackets or other regex specials:
# These behave differently:
grep [a-z] file.txt # Shell tries to expand [a-z] as glob pattern
grep '[a-z]' file.txt # Properly searches for lowercase letters
grep "[a-z]" file.txt # Also works unless $name exists
- Always quote patterns containing spaces or shell metacharacters
- Prefer single quotes for pure regex patterns
- Use double quotes when variable expansion is needed
- Consider -F (fixed strings) when searching literal text
Searching for a single quote:
grep "'hello'" file.txt # Double quotes wrapping single quote
grep \\'hello\\' file.txt # Escaped quotes
Searching with environment variables:
PATTERN="error.*[0-9]"
grep "$PATTERN" logs.txt # Double quotes allow expansion
While quote style doesn't affect grep's performance, proper quoting prevents:
- Unintended shell globbing
- Pattern misinterpretation
- Unnecessary file processing