en un clic
bash
Bash Shell Script Development Guidelines
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Menu
Bash Shell Script Development Guidelines
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Go Project Planning Skill
Godot C# Game Development Skill
Godot Game Development Skill
Golang Development Guidelines
Grill Me - Relentless Design Interview
Helios Design System (Generic)
Basé sur la classification professionnelle 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 diff