JT's Weblog

Bash Gotchas That Will Surprise JavaScript and C# Developers

AI-GENERATED published: October 24, 2025 estimate: 2 min read view-cnt: 0 views

Introduction

If you’re a JavaScript or C# developer venturing into bash scripting, prepare for a culture shock. Here are the gotchas that will make you question everything.

Spaces Are Syntax

In most languages, whitespace is forgiving. Not in bash.

# This works - spaces required around brackets
if [[ $x -eq 5 ]]; then

# This works - NO spaces around =
x=5

# This FAILS - spaces make bash think "x" is a command
x = 5

Assignment requires NO spaces around equals. Conditionals require spaces around brackets. Miss one space and you’ll get cryptic “command not found” errors.

Single vs Double Brackets

Speaking of conditionals, [ ] and [[ ]] look similar but behave very differently.

[ ] is a command (old POSIX test) with word splitting. [[ ]] is a safer bash keyword:

x=""  # empty variable

# FAILS - word splitting breaks it
if [ $x -eq 5 ]; then

# Works - quoted variable
if [ "$x" -eq 5 ]; then

# Works - no word splitting in [[]]
if [[ $x -eq 5 ]]; then

[[ ]] supports pattern matching and regex. Prefer [[ ]] for bash; use [ ] for POSIX compatibility.

Exit Codes Are Backwards

Success is zero. Failure is non-zero. Opposite of JavaScript’s truthy/falsy.

# 0 means success!
if [ $? -eq 0 ]; then
    echo "Command succeeded"
fi

It makes sense: there’s one way to succeed, many ways to fail.

String Comparison Traps

Bash needs different operators for strings vs numbers.

[ "5" = "5" ]   # String comparison (correct)
[ "5" -eq "5" ] # Numeric comparison (also works)
[ "05" = "5" ]  # False - strings differ
[ "05" -eq "5" ] # True - numeric comparison

Use -eq, -ne, -lt, -gt for numbers. Use =, != for strings.

Arrays Start at Zero, But…

Arrays are zero-indexed, but the syntax is bonkers:

arr=(one two three)
echo ${arr[0]}      # "one"
echo $arr           # Also "one" - without brackets!
echo ${arr[@]}      # All elements
echo ${#arr[@]}     # Array length

Curly braces and @ required beyond the first element.

Quotes Matter Everywhere

files="file with spaces.txt"
rm $files           # Tries to delete "file", "with", "spaces.txt"
rm "$files"         # Deletes the correct file

Unquoted variables split on whitespace. Always quote.

Return Values Are Limited

Functions can only return integers 0-255. Want to return a string? Use echo and capture it with command substitution:

get_name() {
    echo "John"
}

name=$(get_name)  # Capture stdout

Conclusion

These gotchas stem from bash’s shell heritage. Learn them once, and muscle memory takes over.

Happy scripting!



No comments yet

Be the first to comment!