Back to list
knopki

shell-scripting-fundamentals

by knopki

There's no place like $HOME

0🍴 0📅 Jan 24, 2026

SKILL.md


name: shell-scripting-fundamentals description: Use when writing or modifying Bash/shell scripts. Covers script structure, variables, quoting, conditionals, and loops with modern best practices.

Shell Scripting Fundamentals

Core patterns and best practices for writing robust, maintainable shell scripts.

Script Structure

Always start scripts with a proper shebang and safety options:

#!/usr/bin/env bash
set -euo pipefail

# Script description here

Safety Options Explained

  • set -e: Exit on any command failure
  • set -u: Error on undefined variables
  • set -o pipefail: Pipeline fails if any command fails

Variables

Declaration and Assignment

# No spaces around =
name="value"

# readonly for constants
readonly CONFIG_DIR="/etc/myapp"

# local in functions
my_function() {
    local result="computed"
    echo "$result"
}

Always Quote Variables

# Good - prevents word splitting and glob expansion
echo "$variable"
cp "$source" "$destination"

# Bad - can break on spaces or special characters
echo $variable
cp $source $destination

Default Values

# Use default if unset
name="${NAME:-default}"

# Use default if unset or empty
name="${NAME:-}"

# Assign default if unset
: "${NAME:=default}"

# Error if unset
: "${REQUIRED_VAR:?Error: REQUIRED_VAR must be set}"

Conditionals

Test Syntax

# Modern syntax - preferred
if [[ -f "$file" ]]; then
    echo "File exists"
fi

# String comparison
if [[ "$string" == "value" ]]; then
    echo "Match"
fi

# Numeric comparison
if (( count > 10 )); then
    echo "Greater than 10"
fi

# Regex matching
if [[ "$input" =~ ^[0-9]+$ ]]; then
    echo "Numeric input"
fi

Common Test Operators

OperatorDescription
-fFile exists and is regular file
-dDirectory exists
-ePath exists
-rReadable
-wWritable
-xExecutable
-zString is empty
-nString is not empty

Loops

For Loops

# Iterate over list
for item in one two three; do
    echo "$item"
done

# Iterate over files (use glob, not ls)
for file in *.txt; do
    [[ -e "$file" ]] || continue  # Handle no matches
    process "$file"
done

# C-style for loop
for (( i = 0; i < 10; i++ )); do
    echo "$i"
done

While Loops

# Read lines from file
while IFS= read -r line; do
    echo "$line"
done < "$filename"

# Read with process substitution
while IFS= read -r line; do
    echo "$line"
done < <(some_command)

Arrays

# Declare array
declare -a files=()

# Add elements
files+=("file1.txt")
files+=("file2.txt")

# Iterate all elements
for file in "${files[@]}"; do
    echo "$file"
done

# Get array length
echo "${#files[@]}"

# Access by index
echo "${files[0]}"

Command Substitution

# Modern syntax - preferred
result=$(command)

# Nested substitution
result=$(echo $(date))

# Avoid legacy backticks
result=`command`  # Don't use this

Functions

# Function definition
process_file() {
    local file="$1"
    local output_dir="${2:-./output}"

    if [[ ! -f "$file" ]]; then
        echo "Error: File not found: $file" >&2
        return 1
    fi

    # Process the file
    cp "$file" "$output_dir/"
}

# Call with arguments
process_file "input.txt" "/tmp/output"

Best Practices Summary

  1. Always use #!/usr/bin/env bash for portability
  2. Enable strict mode: set -euo pipefail
  3. Quote all variable expansions
  4. Use [[ ]] instead of [ ] for tests
  5. Use $(command) instead of backticks
  6. Declare local variables in functions
  7. Use arrays for lists of items
  8. Check command existence before use: command -v cmd >/dev/null

Score

Total Score

55/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

0/10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

1ヶ月以内に更新

+10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

+5

Reviews

💬

Reviews coming soon