Loading...
Loading...
This skill should be used when the user asks to "write a bash script", "follow shell style guide", "format shell scripts", "create shell utilities", or needs guidance on Bash/shell scripting best practices and conventions.
npx skill4agent add the-perfect-developer/the-perfect-opencode bash-shell#!/bin/bashset.shPATH.shif [[ -f "${config_file}" ]]; then
source "${config_file}"
fi# Using here-document
cat <<END
This is a long message that
spans multiple lines.
END
# Using embedded newlines
long_string="This is a long message
that spans multiple lines."; then; do# Correct
for dir in "${dirs_to_cleanup[@]}"; do
if [[ -d "${dir}" ]]; then
rm -rf "${dir}"
fi
done
# Loop variables should be local in functions
local dir
for dir in "${dirs_to_cleanup[@]}"; do
# Process directory
done"${var}""$var"# Preferred
echo "PATH=${PATH}, PWD=${PWD}, mine=${some_var}"
# Acceptable for special variables
echo "Positional: $1" "$5" "$3"
echo "Exit status: $?""$@"$*# Quote variables
echo "${flag}"
# Quote command substitutions
flag="$(some_command and its args "$@")"
# Use arrays for lists
declare -a FLAGS
FLAGS=(--foo --bar='baz')
mybinary "${FLAGS[@]}"[[ … ]][ … ]# Preferred - supports pattern matching
if [[ "${filename}" =~ ^[[:alnum:]]+name ]]; then
echo "Match"
fi
# String comparisons
if [[ "${my_var}" == "some_string" ]]; then
do_something
fi
# Test for empty strings
if [[ -z "${my_var}" ]]; then
echo "Variable is empty"
fi
# Test for non-empty strings
if [[ -n "${my_var}" ]]; then
echo "Variable is not empty"
fi(( … ))# Arithmetic comparisons
if (( my_var > 3 )); then
do_something
fi
# Calculations
local -i hundred="$(( 10 * 10 ))"
(( i += 3 ))# Single function
my_func() {
local arg1="$1"
local result
result="$(process "${arg1}")"
echo "${result}"
}
# Package-namespaced function
mypackage::my_func() {
…
}#######################################
# Cleanup files from the backup directory.
# Globals:
# BACKUP_DIR
# ORACLE_SID
# Arguments:
# None
# Returns:
# 0 on success, non-zero on error
#######################################
cleanup() {
rm -rf "${BACKUP_DIR}/${ORACLE_SID}/"*
}my_function() {
local my_variable="value"
}readonly PATH_TO_FILES='/some/path'
declare -xr ORACLE_SID='PROD'for zone in "${zones[@]}"; do
process_zone "${zone}"
doneerr() {
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
}
if ! do_something; then
err "Unable to do_something"
exit 1
fi# Direct check
if ! mv "${file}" "${dest_dir}/"; then
echo "Unable to move ${file} to ${dest_dir}" >&2
exit 1
fi
# Using $?
mv "${file}" "${dest_dir}/"
if (( $? != 0 )); then
echo "Unable to move ${file}" >&2
exit 1
fi
# Check pipeline status
tar -cf - ./* | (cd "${dir}" && tar -xf -)
if (( PIPESTATUS[0] != 0 || PIPESTATUS[1] != 0 )); then
echo "Unable to tar files to ${dir}" >&2
fi$(command)# Preferred
var="$(command "$(command1)")"
# Avoid
var="`command \`command1\``"# Good
declare -a files
files=(file1.txt file2.txt "file with spaces.txt")
for file in "${files[@]}"; do
process "${file}"
done
# Avoid
files="file1.txt file2.txt file with spaces.txt"
for file in ${files}; do # Breaks on spaces
process "${file}"
donelocalmy_func() {
local name="$1"
local my_var
# Separate declaration and assignment for command substitution
my_var="$(get_value)"
(( $? == 0 )) || return
}mainmain() {
local config_file="$1"
if [[ ! -f "${config_file}" ]]; then
err "Config file not found: ${config_file}"
return 1
fi
process_config "${config_file}"
}
main "$@"eval# Good
rm -v ./*
# Bad - files starting with - cause issues
rm -v *readarray# Good - preserves variables
while read -r line; do
last_line="${line}"
done < <(your_command)
# Or use readarray
readarray -t lines < <(your_command)
for line in "${lines[@]}"; do
process "${line}"
done
# Bad - creates subshell, variables don't persist
your_command | while read -r line; do
last_line="${line}" # Won't be visible outside
done#!/bin/bash
#
# Brief description of what this script does.err() {
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
}# Check command success
if ! command; then
err "Command failed"
exit 1
fi
# Test string equality
if [[ "${var}" == "value" ]]; then
do_something
fi
# Test numeric comparison
if (( num > 10 )); then
do_something
fi
# Loop over array
for item in "${array[@]}"; do
process "${item}"
done
# Safe command substitution
result="$(command)"
if (( $? != 0 )); then
err "Command failed"
exit 1
fireferences/google-shell-guide.mdreferences/common-patterns.mdreferences/security-guidelines.mdexamples/basic-script.shadvanced-script.shlibrary-example.sh