Sure, here's a comprehensive shell (Bash) scripting standards document, aligned with the principles and structure we established for the HTML standards. ----- # Shell (Bash) Scripting Standards Documentation ## Introduction This document outlines our conventions and best practices for writing **Shell (Bash) scripts**. Adhering to these standards ensures our scripts are **consistent, readable, maintainable, and robust**. By following these guidelines, we'll foster **easier collaboration**, **reduce debugging time**, and **improve script reliability**. ----- ## Script Structure and Headers Consistent script structure and informative headers are crucial for immediate understanding and maintainability. * **Shebang Line**: Always start with the shebang line specifying the interpreter. * **Description**: Ensures the script runs with Bash, regardless of the user's default shell. * **Usage**: `#!/bin/bash` * **Script Header Comments**: Include a standardized block at the top of each script. * **Description**: Provides essential metadata for quick reference. * **Usage**: ```bash #!/bin/bash # Script Name: myscript.sh # Description: This script automates the backup of project files. # Author: Your Name # Date: 2025-06-30 # Version: 1.0.0 # Usage: ./myscript.sh [--options] # Dependencies: rsync, tar # License: MIT (or your chosen license) ``` * **Error Handling (Immediate Exit)**: * **Description**: Always include `set -e` and `set -u`. * `set -e`: Exit immediately if a command exits with a non-zero status. This prevents scripts from continuing in an error state. * `set -u`: Treat unset variables as an error and exit immediately. This helps catch typos and uninitialized variables. * `set -o pipefail`: (Optional but recommended) Causes a pipeline to return the exit status of the last command in the pipe that exited with a non-zero status, rather than just the last command. * **Usage**: ```bash #!/bin/bash set -euo pipefail # All three combined ``` ----- ## Naming Conventions Consistent naming makes variables, functions, and files easy to identify and understand. ### 1\. Variables * **Lowercase with Underscores (snake\_case)**: * **Description**: For general script variables. * **Usage**: `file_name`, `user_input`, `temp_directory` * **Uppercase with Underscores (SCREAMING\_SNAKE\_CASE)**: * **Description**: For **constants** (values that should not change) and **environment variables**. * **Usage**: `MAX_RETRIES=5`, `LOG_FILE="/var/log/app.log"`, `PATH` * **Positional Parameters**: * **Description**: Refer to script arguments using `$1`, `$2`, etc., and use `$@` for all arguments. * **Usage**: `echo "First arg: $1"`, `for arg in "$@"; do ... done` ### 2\. Functions * **Lowercase with Underscores (snake\_case)**: * **Description**: For function names. Verb-noun structure is often helpful. * **Usage**: `display_help`, `process_file`, `cleanup_temp_files` ### 3\. Files * **Lowercase with Hyphens (kebab-case)**: * **Description**: For script filenames. Avoid spaces. * **Usage**: `backup-database.sh`, `deploy-app.sh`, `monitor-logs.sh` ----- ## Formatting and Readability Clean formatting significantly improves readability and navigability. ### 1\. Indentation * **Spaces over Tabs**: * **Description**: Use **4 spaces** for indentation. Configure your editor to convert tabs to spaces. * **Consistent Indentation**: * **Description**: Indent blocks of code within `if`, `for`, `while`, `function`, etc. consistently. ### 2\. Spacing * **Operators and Assignments**: * **Description**: Use spaces around operators (`=`, `==`, `!=`, `<`, `>`) and assignments. * **Usage**: `variable = "value"`, `if [[ $a -eq $b ]]`, `count=$((count + 1))` * **Function Calls**: * **Description**: No space between function name and parentheses. * **Usage**: `my_function arg1 arg2` (not `my_function(arg1, arg2)`) * **Command Separators**: * **Description**: Use semicolons `;` only for multiple commands on one line, or for simple `if` statements. Prefer new lines. * **Usage**: `command1; command2` (less common), `if [ "$1" == "--help" ]; then display_help; exit 0; fi` ### 3\. Comments * **Descriptive Comments**: * **Description**: Use `#` for single-line comments. Add comments to explain **why** a piece of code exists, not just **what** it does. Complex logic or non-obvious steps should be commented. * **Usage**: ```bash # Validate that the log file exists before proceeding. if [[ ! -f "$LOG_FILE" ]]; then echo "Error: Log file not found at $LOG_FILE" >&2 exit 1 fi ``` * **Block Comments**: * **Description**: For larger explanations or section headers. * **Usage**: ```bash ############################################# # Function: cleanup_old_backups # Description: Deletes backups older than N days. ############################################# ``` ----- ## Best Practices and Principles These principles guide our overall approach to writing effective and maintainable Bash scripts. ### 1\. Modularity and Functions * **Description**: Break down complex scripts into smaller, focused functions. Each function should perform a single, well-defined task. * **Benefit**: Improves readability, reusability, and makes debugging easier. * **Usage**: ```bash function validate_input() { if [[ -z "$1" ]]; then echo "Error: Argument is missing." >&2 exit 1 fi } validate_input "$@" ``` ### 2\. Argument Parsing * **Description**: For scripts that accept options or arguments, use `getopts` for simple options or manual parsing for more complex scenarios. Avoid simple positional checks for multiple options. * **Benefit**: Provides a user-friendly interface and robust argument handling. * **Usage (`getopts` example)**: ```bash while getopts "hv:d:" opt; do case $opt in h) display_help; exit 0 ;; v) VERBOSE=true ;; d) DEST_DIR="$OPTARG" ;; \?) echo "Invalid option: -$OPTARG" >&2; exit 1 ;; esac done shift $((OPTIND - 1)) # Shift positional parameters ``` ### 3\. Error Handling and Logging * **Description**: Beyond `set -e` and `set -u`, implement explicit error checks for critical commands. Redirect error messages to `stderr` (`>&2`) and informative messages to `stdout`. Consider logging to a file for long-running scripts. * **Benefit**: Makes scripts more robust and easier to diagnose issues. * **Usage**: ```bash # Command that might fail cp source_file.txt dest_dir/ || { echo "Error: Failed to copy file." >&2; exit 1; } log_message() { echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE" } log_message "Script started." ``` ### 4\. Quoting Variables * **Description**: **Always quote variables** when they contain spaces or special characters to prevent word splitting and globbing. This is one of the most common Bash pitfalls. * **Benefit**: Prevents unexpected behavior and ensures commands receive arguments as intended. * **Usage**: ```bash # BAD: May cause issues if file has spaces # rm $FILE_PATH # GOOD: Safely handles spaces rm "$FILE_PATH" # For arrays for item in "${my_array[@]}"; do echo "$item" done ``` ### 5\. Using `[[ ... ]]` over `[ ... ]` (where appropriate) * **Description**: Prefer the `[[ ... ]]` (Bash's extended test command) for conditional expressions over the older `[ ... ]` (POSIX `test` command). * **Benefit**: `[[ ... ]]` offers more features (like regex matching `==~`, logical operators `&&`, `||`), is less prone to word splitting issues, and provides better readability. * **Usage**: ```bash if [[ "$variable" == "expected value" ]]; then ... fi if [[ "$string" =~ ^[0-9]+$ ]]; then echo "Is a number"; fi if [[ -f "$file" && -r "$file" ]]; then ... fi ``` ### 6\. Avoid `ls` Parsing * **Description**: Do not parse the output of `ls` (e.g., using `grep` or `awk` on `ls` output) for processing filenames. `ls` output is for human readability, not programmatic use, and can be ambiguous with special characters. * **Benefit**: Prevents subtle bugs when dealing with filenames containing spaces, newlines, or other special characters. * **Instead**: Use globbing or `find -print0 | xargs -0` for safe file processing. * **Usage**: ```bash # BAD: Don't do this! # for file in $(ls *.txt); do ... fi # GOOD: Use globbing for file in *.txt; do echo "Processing '$file'" done # GOOD: For complex find operations find . -name "*.log" -print0 | while IFS= read -r -d $'\0' file; do echo "Found log: $file" done ``` ----- ## Conclusion By diligently applying these **Bash scripting standards**, we ensure our scripts are not only functional but also **highly readable, maintainable, and robust**. This commitment to quality coding practices promotes a more efficient development workflow and strengthens the reliability of our automated tasks.