All skills
akin-ozer avatar

/bash-script-validator

@1b2342a

Validate, lint, audit, or fix bash/shell/.sh scripts via ShellCheck.

Use this Skill: https://skilld.dev/gh/akin-ozer/cc-devops-skills/bash-script-validator

This session only. Nothing lands on disk.

docscommon-mistakes.md

≈2.3k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Common Shell Scripting Mistakes

This guide covers frequent mistakes made in bash and shell scripts, their consequences, and how to fix them.

1. Unquoted Variables

Problem

# Wrong
file=/path/with spaces/file.txt
cat $file  # Breaks into multiple arguments

Consequence

Word splitting and glob expansion cause unexpected behavior.

Solution

# Right
file="/path/with spaces/file.txt"
cat "$file"

Rule

Always quote variable expansions unless you explicitly need word splitting.


2. Not Checking Command Success

Problem

# Wrong
cd /some/directory
rm -rf *  # DANGEROUS if cd fails!

Consequence

Commands execute even if previous commands fail, potentially catastrophic.

Solution

# Right
cd /some/directory || exit 1
rm -rf *

# Or use set -e
set -e
cd /some/directory
rm -rf *

# Or check explicitly
if ! cd /some/directory; then
    echo "Failed to change directory" >&2
    exit 1
fi
rm -rf *

3. Using [ ] with Bash Features

Problem

# Wrong (== not POSIX, may fail in sh)
if [ "$var" == "value" ]; then
    echo "match"
fi

Solution

# POSIX sh - use single =
if [ "$var" = "value" ]; then
    echo "match"
fi

# Or use bash [[ ]] (bash only)
if [[ "$var" == "value" ]]; then
    echo "match"
fi

4. Useless Use of cat (UUOC)

Problem

# Wrong - unnecessary cat
cat file.txt | grep pattern
cat file.txt | awk '{print $1}'

Consequence

Wastes a process, less efficient.

Solution

# Right
grep pattern file.txt
awk '{print $1}' file.txt

# Or use redirection
< file.txt grep pattern

5. Not Using -r with read

Problem

# Wrong
while read line; do
    echo "$line"
done < file

Consequence

Backslashes are interpreted, leading character may be removed.

Solution

# Right
while IFS= read -r line; do
    echo "$line"
done < file
  • -r prevents backslash interpretation
  • IFS= prevents leading/trailing whitespace trimming

6. Testing $? After Multiple Commands

Problem

# Wrong
command1
command2
if [ $? -eq 0 ]; then  # Tests command2, not command1!
    echo "Success"
fi

Solution

# Right - test immediately
command1
if [ $? -eq 0 ]; then
    echo "command1 succeeded"
fi

# Better - test directly
if command1; then
    echo "Success"
fi

7. Arrays in POSIX sh Scripts

Problem

#!/bin/sh
# Wrong - arrays not in POSIX sh
array=(one two three)
echo "${array[0]}"

Solution

# Use bash
#!/bin/bash
array=(one two three)
echo "${array[0]}"

# Or use POSIX alternatives
set -- one two three
echo "$1"

8. Not Declaring Functions Before Use

Problem

# Wrong - function not defined yet
my_function

my_function() {
    echo "Hello"
}

Solution

# Right - define first
my_function() {
    echo "Hello"
}

my_function

9. Using eval Unsafely

Problem

# DANGEROUS
user_input="$1"
eval "$user_input"  # Command injection risk!

Consequence

Security vulnerability - arbitrary code execution.

Solution

# Avoid eval when possible
# If necessary, sanitize input thoroughly
# Or use safer alternatives

# Example: dynamic variable names
var_name="my_var"
# Don't: eval "echo \$$var_name"
# Do: Use indirect expansion (bash)
echo "${!var_name}"

10. Forgetting set -u

Problem

# Wrong - typo goes unnoticed
nmae="John"  # Typo
echo "Hello, $name"  # Prints "Hello, " (empty)

Solution

# Right - use set -u
set -u
nmae="John"  # Typo
echo "Hello, $name"  # Error: name: unbound variable

11. Incorrect String Comparison

Problem

# Wrong - numeric comparison on strings
if [ "$version" -gt "2.0" ]; then
    echo "New version"
fi

Solution

# Right - string comparison
if [ "$version" = "2.0" ]; then
    echo "Exact match"
fi

# Or use proper version comparison
if [[ "$version" > "2.0" ]]; then
    echo "Greater"
fi

12. Not Handling Spaces in Filenames

Problem

# Wrong
for file in $(ls *.txt); do
    echo "$file"
done

Consequence

Files with spaces break into multiple items.

Solution

# Right - use glob directly
for file in *.txt; do
    echo "$file"
done

# Or use find with -print0
while IFS= read -r -d '' file; do
    echo "$file"
done < <(find . -name "*.txt" -print0)

13. Backticks Instead of $()

Problem

# Deprecated
result=`command arg1 arg2`

Solution

# Modern
result=$(command arg1 arg2)

Why

  • Better nesting: $(cmd1 $(cmd2))
  • Better readability
  • Fewer escaping issues

14. Using = Instead of == in [[ ]]

Not really a mistake, but inconsistent:

# Both work in [[ ]]
[[ "$var" = "value" ]]   # POSIX style (works)
[[ "$var" == "value" ]]  # Bash style (also works)

# Only = works in [ ]
[ "$var" = "value" ]     # Works
[ "$var" == "value" ]    # May fail in POSIX sh

Recommendation: Use = for portability, or stick to == in bash with [[ ]].


15. Not Quoting $@

Problem

# Wrong
script.sh "$@"  # Right
command $@      # Wrong if args have spaces

Solution

# Right
command "$@"  # Preserves argument boundaries

16. Using ls to Process Files

Problem

# Wrong
files=$(ls *.txt)
for file in $files; do
    process "$file"
done

Issues

  • Breaks on spaces
  • Breaks on newlines in filenames
  • Breaks on glob characters

Solution

# Right
for file in *.txt; do
    process "$file"
done

# Or with find
find . -name "*.txt" -exec process {} \;

17. Incorrect Exit Codes

Problem

# Wrong
function check_file() {
    if [ -f "$1" ]; then
        echo "File exists"
        return 1  # Success should be 0!
    fi
    return 0
}

Solution

# Right - 0 is success, non-zero is failure
function check_file() {
    if [ -f "$1" ]; then
        echo "File exists"
        return 0
    fi
    return 1
}

18. Using -a and -o in [ ]

Problem

# Deprecated and error-prone
[ "$a" = "x" -a "$b" = "y" ]
[ "$a" = "x" -o "$b" = "y" ]

Solution

# Right - use && and ||
[ "$a" = "x" ] && [ "$b" = "y" ]
[ "$a" = "x" ] || [ "$b" = "y" ]

# Or use [[ ]] in bash
[[ "$a" = "x" && "$b" = "y" ]]
[[ "$a" = "x" || "$b" = "y" ]]

19. Not Making Scripts Executable

Problem

# Wrong
bash script.sh  # Works but not ideal

Solution

# Right
chmod +x script.sh
./script.sh

And include proper shebang:

#!/usr/bin/env bash

20. Forgetting Final Newline

Problem

Some tools expect files to end with a newline.

Solution

Ensure your editor adds a final newline, or:

echo "" >> file

21. Using grep -q Without Knowing Implications

Problem

# Potentially inefficient
if [ "$(grep pattern file)" ]; then
    echo "Found"
fi

Solution

# Better - grep -q exits on first match
if grep -q pattern file; then
    echo "Found"
fi

22. Incorrect glob Pattern

Problem

# Wrong - doesn't match hidden files
for file in *; do
    process "$file"
done

Solution

# Include hidden files (bash)
shopt -s dotglob
for file in *; do
    process "$file"
done
shopt -u dotglob

# Or explicitly
for file in * .[!.]* ..?*; do
    [ -e "$file" ] && process "$file"
done

23. Not Handling Empty Globs

Problem

# Fails if no .txt files
for file in *.txt; do
    process "$file"  # Processes literal "*.txt"
done

Solution

# Bash - fail gracefully
shopt -s nullglob
for file in *.txt; do
    process "$file"
done
shopt -u nullglob

# POSIX - check existence
for file in *.txt; do
    [ -e "$file" ] || continue
    process "$file"
done

24. Not Sanitizing Input

Problem

# Dangerous
rm -rf "/$1"  # What if $1 is empty or manipulated?

Solution

# Safer
if [ -z "$1" ]; then
    echo "Error: No argument provided" >&2
    exit 1
fi

# Validate
case "$1" in
    /*)
        echo "Error: Absolute paths not allowed" >&2
        exit 1
        ;;
esac

rm -rf "$1"

25. Using -e for File Existence

Not a mistake, but be specific:

[ -e "$file" ]  # Exists (any type)
[ -f "$file" ]  # Regular file
[ -d "$file" ]  # Directory
[ -L "$file" ]  # Symbolic link
[ -r "$file" ]  # Readable
[ -w "$file" ]  # Writable
[ -x "$file" ]  # Executable

Quick Checklist

Before running a script, verify:

  • Proper shebang (#!/bin/bash or #!/bin/sh)
  • set -euo pipefail (strict mode)
  • All variables quoted
  • Error handling for critical commands
  • Using $() not backticks
  • Not using ls for file processing
  • Functions defined before use
  • Proper exit codes (0 = success)
  • Input validation
  • ShellCheck passes

Resources

Source: SKILL.md on GitHub

2 warnings16d4 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    The skill provides a Bash and POSIX shell script validator using ShellCheck and custom linting logic. It includes a fallback mechanism to automatically install the ShellCheck binary via a Python virtual environment from PyPI if it is missing on the system. No malicious behavior was identified.

  • Socket16d

    2 alerts: gptSecurity

  • Snyk16d

    Risk: MEDIUM · 1 issue

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 1b2342a. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Steadyupdated 7 months ago

README badge

README badge for akin-ozer/cc-devops-skills/bash-script-validator