بنقرة واحدة
bash
Bash Shell Script Development Guidelines
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Bash Shell Script Development Guidelines
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
| name | bash |
| description | Bash Shell Script Development Guidelines |
High-quality, maintainable bash shell scripts following industry best practices.
#!/usr/bin/env bash at the top of every scriptset -euo pipefail for error handling"$variable" not $variablecommand -vshellcheck and shfmt before completing any scripteval unless absolutely necessary and after careful security reviewls output - use globs or find insteadBefore completing any bash script, ALL must pass:
shellcheck script.sh # REQUIRED - must pass with no errors or warnings
shfmt -d script.sh # REQUIRED - must have no diff (properly formatted)
To auto-format a script:
shfmt -w script.sh
Fix all shellcheck errors and warnings. Do not use # shellcheck disable= directives unless absolutely necessary and justified.
#!/usr/bin/env bash
# Script: script_name.sh
# Description: Brief description of what the script does
# Usage: script_name.sh [options] [arguments]
set -euo pipefail
# Configuration - declare and assign separately to avoid SC2155
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly SCRIPT_DIR
SCRIPT_NAME="$(basename "${BASH_SOURCE[0]}")"
readonly SCRIPT_NAME
# Color codes for output (optional)
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly NC='\033[0m' # No Color
# Functions
usage() {
cat <<EOF
Usage: ${SCRIPT_NAME} [OPTIONS] [ARGUMENTS]
Description of what this script does.
OPTIONS:
-h, --help Show this help message
-v, --verbose Enable verbose output
-d, --debug Enable debug mode
ARGUMENTS:
arg1 Description of argument 1
arg2 Description of argument 2
EXAMPLES:
${SCRIPT_NAME} --verbose file.txt
${SCRIPT_NAME} -d input.txt output.txt
EOF
}
log_info() {
echo -e "${GREEN}[INFO]${NC} $*" >&2
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $*" >&2
}
log_error() {
echo -e "${RED}[ERROR]${NC} $*" >&2
}
cleanup() {
# Cleanup code here (temp files, etc.)
:
}
main() {
# Main script logic here
:
}
# Trap errors and cleanup
trap cleanup EXIT
trap 'log_error "Script failed at line $LINENO"' ERR
# Parse arguments and run main
main "$@"
Use set -euo pipefail:
set -e: Exit on errorset -u: Exit on undefined variableset -o pipefail: Exit on pipe failureCheck command exit codes explicitly when needed:
if ! command_that_might_fail; then
log_error "Command failed"
exit 1
fi
Use trap for cleanup:
trap cleanup EXIT
trap 'log_error "Error at line $LINENO"' ERR
Always quote variables:
# Good
cp "$source" "$destination"
# Bad
cp $source $destination
Quote command substitutions:
# Good
result="$(some_command)"
# Bad
result=$(some_command)
Use arrays for lists:
# Good
files=("file1.txt" "file 2.txt" "file3.txt")
for file in "${files[@]}"; do
process "$file"
done
# Bad
files="file1.txt file 2.txt file3.txt"
for file in $files; do
process $file
done
Use [[ ]] instead of [ ]:
# Good - modern bash
if [[ "$var" == "value" ]]; then
echo "Match"
fi
Check if variable is set:
# Check if set and non-empty
if [[ -n "${var:-}" ]]; then
echo "Variable is set"
fi
# Check if unset or empty
if [[ -z "${var:-}" ]]; then
echo "Variable is not set"
fi
File tests:
if [[ -f "$file" ]]; then echo "Regular file exists"; fi
if [[ -d "$dir" ]]; then echo "Directory exists"; fi
if [[ -x "$script" ]]; then echo "File is executable"; fi
if [[ -r "$file" ]]; then echo "File is readable"; fi
Use $() instead of backticks:
# Good
result="$(command)"
# Bad
result=`command`
Check if command exists before using:
if ! command -v jq &> /dev/null; then
log_error "jq is not installed"
exit 1
fi
Use local variables:
process_file() {
local file="$1"
local output="${2:-output.txt}"
# Process the file
cat "$file" > "$output"
}
Return values properly:
# For numeric return codes (0-255)
check_status() {
if [[ -f "$1" ]]; then
return 0 # Success
else
return 1 # Failure
fi
}
# For string output, use echo
get_filename() {
local path="$1"
echo "$(basename "$path")"
}
Use getopts for simple cases:
while getopts "hvd:" opt; do
case $opt in
h) usage; exit 0 ;;
v) verbose=1 ;;
d) directory="$OPTARG" ;;
\?) log_error "Invalid option: -$OPTARG"; exit 1 ;;
esac
done
shift $((OPTIND - 1))
Manual parsing for long options:
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
usage
exit 0
;;
-v|--verbose)
verbose=1
shift
;;
-o|--output)
output="$2"
shift 2
;;
*)
log_error "Unknown option: $1"
exit 1
;;
esac
done
Read file line by line:
while IFS= read -r line; do
echo "Line: $line"
done < "$file"
Process files matching pattern:
# Using glob
for file in *.txt; do
[[ -f "$file" ]] || continue
process "$file"
done
# Using find for complex patterns
while IFS= read -r -d '' file; do
process "$file"
done < <(find . -name "*.txt" -type f -print0)
Create temporary files/directories:
temp_file="$(mktemp)"
temp_dir="$(mktemp -d)"
cleanup() {
rm -f "$temp_file"
rm -rf "$temp_dir"
}
trap cleanup EXIT
Parameter expansion:
# Remove prefix/suffix
filename="${path##*/}" # basename
directory="${path%/*}" # dirname
extension="${filename##*.}" # file extension
basename="${filename%.*}" # filename without extension
# Default values
value="${var:-default}" # Use default if var is unset/empty
value="${var:=default}" # Assign default if var is unset/empty
# String replacement
new="${old/pattern/replacement}" # Replace first occurrence
new="${old//pattern/replacement}" # Replace all occurrences
String length and substrings:
length="${#string}"
substring="${string:0:5}" # First 5 characters
substring="${string: -5}" # Last 5 characters
Array operations:
# Declaration
array=("item1" "item2" "item3")
# Access elements
echo "${array[0]}" # First element
echo "${array[@]}" # All elements
echo "${#array[@]}" # Array length
# Iteration
for item in "${array[@]}"; do
echo "$item"
done
# Add elements
array+=("item4")
Associative arrays (bash 4+):
declare -A map
map["key1"]="value1"
map["key2"]="value2"
# Iterate
for key in "${!map[@]}"; do
echo "$key: ${map[$key]}"
done
Never use user input directly in commands:
# Bad - command injection vulnerability
eval "rm $user_input"
# Good - validate and sanitize
if [[ "$user_input" =~ ^[a-zA-Z0-9_-]+$ ]]; then
rm -f "$user_input"
fi
Use full paths for commands in scripts run as root:
# Good
/usr/bin/rm -f "$file"
# Risky if PATH is modified
rm -f "$file"
Set secure permissions on sensitive scripts:
chmod 700 sensitive_script.sh # Owner only
chmod 755 public_script.sh # All can read/execute
Avoid exposing secrets in process list:
# Bad - password visible in ps
mysql -p"$password" -e "SELECT * FROM users"
# Good - use config file
mysql --defaults-file="$config_file" -e "SELECT * FROM users"
Parsing ls output:
# Bad
for file in $(ls *.txt); do
process "$file"
done
# Good
for file in *.txt; do
[[ -f "$file" ]] || continue
process "$file"
done
Unquoted variables:
# Bad
if [ $var == $other ]; then
# Good
if [[ "$var" == "$other" ]]; then
Using echo for output that might contain flags:
# Bad - can interpret flags
echo "$user_input"
# Good
printf '%s\n' "$user_input"
Cat abuse (UUOC - Useless Use of Cat):
# Bad
cat file.txt | grep pattern
# Good
grep pattern file.txt
Not checking if commands exist:
# Bad
jq '.field' file.json
# Good
if ! command -v jq &> /dev/null; then
log_error "jq is required but not installed"
exit 1
fi
jq '.field' file.json
Always run shellcheck on scripts - all errors and warnings must be fixed:
shellcheck script.sh
Common issues and fixes:
| Error | Fix |
|---|---|
| SC2155 | Declare and assign separately: VAR=$(cmd) then readonly VAR |
| SC2086 | Quote the variable: "$var" not $var |
| SC2046 | Quote command substitution: "$(cmd)" not $(cmd) |
| SC2164 | Add ` |
| SC2071 | Use -lt/-gt for numbers: [[ $a -lt $b ]] not [[ $a < $b ]] |
Avoid using disable directives - fix the underlying issue instead.
Always format scripts with shfmt:
# Check formatting (shows diff if not formatted)
shfmt -d script.sh
# Auto-format in place
shfmt -w script.sh
#!/usr/bin/env bash)set -euo pipefail usedls outputlocal variableseval without justification[[ ]] used instead of [ ]shellcheck passes with no errors or warningsshfmt -d shows no diffGo Project Planning Skill
Godot C# Game Development Skill
Godot Game Development Skill
Golang Development Guidelines
Grill Me - Relentless Design Interview
Helios Design System (Generic)