Problem Statement
Explain the differences between [ ], [[ ]], and (( )) for conditionals in bash. When should you use each?
Explanation
Single brackets [ ] are the traditional test command, POSIX-compatible working in all shells. Requires careful quoting of variables to prevent word splitting: [ "$VAR" = "value" ]. Spaces around brackets and operators required. Operators: = or == for string equality, != for inequality, -eq, -ne, -gt, -lt, -ge, -le for numeric comparison. Combine with -a (AND), -o (OR), ! (NOT).
Double brackets [[ ]] are bash-specific with enhanced features: pattern matching [[ $VAR == pattern ]], regex matching [[ $VAR =~ regex ]], no word splitting (quotes often optional), && and || operators instead of -a/-o, no pathname expansion inside. Example: [[ $FILE == *.txt ]] checks if FILE ends with .txt without needing quotes. More forgiving and powerful but not POSIX-portable.
Double parentheses (( )) for arithmetic evaluation: supports C-style operators (+, -, *, /, %, ++, --), comparison operators (>, <, >=, <=, ==, !=), logical operators (&&, ||, !), no need for $ on variables inside. Example: if (( VAR > 10 )); then echo "Greater"; fi. Returns true (0) if expression is non-zero. Use for all numeric comparisons and calculations.
Comparison:
- [ ] most portable, use for POSIX scripts or maximum compatibility
- [[ ]] most powerful for bash, use when bash-specific features needed (pattern matching, regex)
- (( )) for arithmetic, use for all numeric operations and comparisons
Best practices: use [[ ]] in bash scripts for string operations and file tests (cleaner, more powerful), use (( )) for numeric operations (clearer intent, proper arithmetic), use [ ] only when POSIX portability required. Understanding these differences enables writing correct, efficient conditional logic.