Back to Freecodecamp

Bash Scripting Review

curriculum/challenges/english/blocks/review-bash-scripting/6724e417419c2f211bb41bfc.md

latest20.6 KB
Original Source

--description--

Bash Scripting Basics

  • Bash scripting: Writing a sequence of Bash commands in a file, which you can then execute with Bash to run the contents of the file.

  • Shebang: The commented line at the beginning of a script (e.g., #!/bin/bash) that indicates what interpreter should be used for the script.

    bash
    #!/bin/bash
    
  • Variable assignment: Instantiate variables using the syntax variable_name=value.

    bash
    servers=("prod" "dev")
    
  • Variable creation rules: Create variables with VARIABLE_NAME=VALUE syntax. No spaces are allowed around the equal sign (=). Use double quotes if the value contains spaces.

    bash
    NAME=John
    MESSAGE="Hello World"
    COUNT=5
    TEXT="The next number is, "
    
  • Variable usage: Access variable values by placing $ in front of the variable name.

    bash
    echo $NAME
    echo "The message is: $MESSAGE"
    
  • Variable interpolation: Use $variable_name to access the value of a variable within strings and commands.

    bash
    TEXT="The next number is, "
    NUMBER=42
    echo $TEXT B:$NUMBER
    echo $TEXT I:$NUMBER
    
    echo "Pulling $server"
    rsync --archive --verbose $server:/etc/nginx/conf.d/server.conf configs/$server.conf
    
  • Variable scope: Shell scripts run from top to bottom, so variables can only be used below where they are created.

    bash
    NAME="Alice"
    echo $NAME
    
  • User input: Use read to accept input from users and store it in a variable.

    bash
    read USERNAME
    echo "Hello $USERNAME"
    
  • Comments: Add comments to your scripts using # followed by your comment text.

    • Single-line comments start with # and continue to the end of the line
    • Comments are ignored by the shell and don't affect script execution
    bash
    # This is a single-line comment
    NAME="John"  # Comment at end of line
    
  • Multi-line comments: Comment out blocks of code using colon and quotes.

    bash
    : '
    This is a multi-line comment
    Everything between the quotes is ignored
    Useful for debugging or documentation
    '
    
  • Built-in commands and help:

    • Use help to see a list of built-in bash commands
    • Use help <command> to get information about specific built-in commands
    • Some commands (like if) are built-ins and don't have man pages
    • Built-in commands are executed directly by the shell rather than as external programs
    • Use help function to see information about creating functions
    bash
    help
    help if
    help function
    
  • Finding command locations: Use which to locate where executables are installed.

    • Shows the full path to executable files
    • Useful for finding interpreter locations (like bash)
    • Helps verify which version of a command will be executed
    bash
    which bash
    which python
    which ls
    
  • Manual pages: Use man to access detailed documentation for commands.

    • Provides comprehensive information about command usage
    • Shows all available options and examples
    • Use arrow keys to navigate, 'q' to quit
    • Not all commands have manual pages (built-ins use help instead)
    bash
    man echo
    man ls
    man bash
    
  • Help flags: Many commands support --help for quick help information.

    • Alternative to manual pages for quick reference
    • Shows command syntax and common options
    • Not all commands support this flag (some may show error)
    bash
    ls --help
    chmod --help
    mv --help
    
  • Echo command options: The echo command supports various options:

    • -e option enables interpretation of backslash escapes
    • \n creates a new line
    • Empty lines are only printed when values are enclosed in quotes
    • Useful for creating formatted output and program titles
    bash
    echo -e "Line 1\nLine 2"
    echo ""
    echo -e "\n~~ Program Title ~~\n"
    echo "Line 1\nLine 2"
    
  • Script arguments: Programs can accept arguments that are accessible using $ variables.

    • $* prints all arguments passed to the script
    • $@ prints all arguments passed to the script as separate quoted strings
    • $<number> accesses specific arguments by position (e.g., $1, $2, $3)
    bash
    echo $*
    echo $@
    echo $1
    echo $2
    

Double Bracket Expressions [[ ]]

  • Double bracket syntax: Use [[ ]] for conditional testing and pattern matching.

    • Must have spaces inside the brackets and around operators
    • Returns exit status 0 (true) or 1 (false) based on the test result
    bash
    [[ $variable == "value" ]]
    [[ $number -gt 10 ]]
    [[ -f filename.txt ]]
    
  • String comparison operators: Compare strings using various operators within [[ ]].

    • == (equal): Tests if two strings are identical
    • != (not equal): Tests if two strings are different
    • < (lexicographically less): String comparison in alphabetical order
    • > (lexicographically greater): String comparison in alphabetical order
    bash
    [[ "apple" == "apple" ]]
    [[ "apple" != "orange" ]]
    [[ "apple" < "banana" ]]
    [[ "zebra" > "apple" ]]
    
  • Numeric comparison operators: Compare numbers using specific numeric operators.

    • -eq (equal): Numeric equality comparison
    • -ne (not equal): Numeric inequality comparison
    • -lt (less than): Numeric less than comparison
    • -le (less than or equal): Numeric less than or equal comparison
    • -gt (greater than): Numeric greater than comparison
    • -ge (greater than or equal): Numeric greater than or equal comparison
    bash
    [[ $number -eq 5 ]]
    [[ $count -ne 0 ]]
    [[ $age -ge 18 ]]
    [[ $score -lt 100 ]]
    
  • Logical operators: Combine multiple conditions using logical operators.

    • && (and): Both conditions must be true
    • || (or): At least one condition must be true
    • ! (not): Negates the condition (makes true false, false true)
    bash
    [[ $age -ge 18 && $age -le 65 ]]
    [[ $name == "John" || $name == "Jane" ]]
    [[ ! -f missing_file.txt ]]
    
  • File test operators: Test file properties and existence.

    • -e file: True if file exists
    • -f file: True if file exists and is a regular file
    • -d file: True if file exists and is a directory
    • -r file: True if file exists and is readable
    • -w file: True if file exists and is writable
    • -x file: True if file exists and is executable
    • -s file: True if file exists and has size greater than zero
    bash
    [[ -e /path/to/file ]]
    [[ -f script.sh ]]
    [[ -d /home/user ]]
    [[ -x program ]]
    
  • Pattern matching with =~: Use regular expressions for advanced pattern matching.

    • =~ operator enables regex pattern matching
    • Pattern should not be quoted when using regex metacharacters
    • Supports full regular expression syntax
    • Case-sensitive by default
    bash
    [[ "hello123" =~ [0-9]+ ]]
    [[ "[email protected]" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]
    [[ "filename.txt" =~ \.txt$ ]]
    
  • Variable existence testing: Check if variables are set or empty.

    • Test if variable is empty: [[ ! $variable ]]
    bash
    [[ ! $undefined_var ]]
    

Double Parentheses Expressions (( ))

  • Arithmetic evaluation: Use (( )) for mathematical calculations and numeric comparisons.

    • Evaluates arithmetic expressions using C-style syntax
    • Variables don't need $ prefix inside double parentheses
    • Returns exit status 0 if result is non-zero, 1 if result is zero
    • Supports all standard arithmetic operators
    bash
    (( result = 10 + 5 ))
    (( count++ ))
    (( total += value ))
    
  • Arithmetic operators: Mathematical operators available in (( )).

    • + (addition): Add two numbers
    • - (subtraction): Subtract second number from first
    • * (multiplication): Multiply two numbers
    • / (division): Divide first number by second (integer division)
    • % (modulo): Remainder after division
    • ** (exponentiation): Raise first number to power of second
    bash
    (( sum = a + b ))
    (( diff = x - y ))
    (( product = width * height ))
    (( remainder = num % 10 ))
    (( power = base ** exponent ))
    
  • Assignment operators: Modify variables using arithmetic assignment operators.

    • = (assignment): Assign value to variable
    • += (add and assign): Add value to variable
    • -= (subtract and assign): Subtract value from variable
    • *= (multiply and assign): Multiply variable by value
    • /= (divide and assign): Divide variable by value
    • %= (modulo and assign): Set variable to remainder
    bash
    (( counter = 0 ))
    (( counter += 5 ))
    (( total -= cost ))
    (( area *= 2 ))
    (( value /= 3 ))
    
  • Increment and decrement operators: Modify variables by one.

    • ++variable (pre-increment): Increment before use
    • variable++ (post-increment): Increment after use
    • --variable (pre-decrement): Decrement before use
    • variable-- (post-decrement): Decrement after use
    bash
    (( ++counter ))
    (( index++ ))
    (( --remaining ))
    (( attempts-- ))
    
  • Comparison operators: Compare numbers using arithmetic comparison.

    • == (equal): Numbers are equal
    • != (not equal): Numbers are not equal
    • < (less than): First number is less than second
    • <= (less than or equal): First number is less than or equal to second
    • > (greater than): First number is greater than second
    • >= (greater than or equal): First number is greater than or equal to second
    bash
    (( age >= 18 ))
    (( score < 100 ))
    (( count == 0 ))
    (( temperature > freezing ))
    
  • Logical operators: Combine arithmetic conditions.

    • && (and): Both conditions must be true
    • || (or): At least one condition must be true
    • ! (not): Negates the condition
    bash
    (( age >= 18 && age <= 65 ))
    (( score >= 90 || extra_credit > 0 ))
    (( !(count == 0) ))
    
  • Bitwise operators: Perform bit-level operations on integers.

    • & (bitwise AND): AND operation on each bit
    • | (bitwise OR): OR operation on each bit
    • ^ (bitwise XOR): XOR operation on each bit
    • ~ (bitwise NOT): Invert all bits
    • << (left shift): Shift bits to the left
    • >> (right shift): Shift bits to the right
    bash
    (( result = a & b ))
    (( flags |= new_flag ))
    (( shifted = value << 2 ))
    
  • Conditional (ternary) operator: Use condition ? true_value : false_value syntax.

    • Provides a concise way to assign values based on conditions
    • Similar to the ternary operator in C-style languages
    • Evaluates condition and returns one of two values
    bash
    (( result = (score >= 60) ? 1 : 0 ))
    (( max = (a > b) ? a : b ))
    (( sign = (num >= 0) ? 1 : -1 ))
    
  • Command substitution with arithmetic: Use $(( )) to capture arithmetic results.

    • Returns the result of the arithmetic expression as a string
    • Can be used in assignments or command arguments
    • Useful for calculations that need to be used elsewhere
    bash
    result=$(( 10 + 5 ))
    echo "The answer is $(( a * b ))"
    array_index=$(( RANDOM % array_length ))
    

Control Flow and Conditionals

  • Conditional statements: Use if statements to execute code based on conditions.

    • Basic syntax: if [[ CONDITION ]] then STATEMENTS fi
    • Full syntax: if [[ CONDITION ]] then STATEMENTS elif [[ CONDITION ]] then STATEMENTS else STATEMENTS fi
    • Can use both [[ ]] and (( )) expressions for different types of conditions
    • elif (else if): Optional, can be repeated multiple times to test additional conditions in sequence
    • else: Optional, executes when all previous conditions are false
    • Can mix double parentheses (( ... )) and double brackets [[ ... ]] in same conditional chain
    bash
    if (( NUMBER <= 15 ))
    then
        echo "B:$NUMBER"
    elif [[ $NUMBER -le 30 ]]
    then
        echo "I:$NUMBER"
    elif (( NUMBER < 46 ))
    then
        echo "N:$NUMBER"
    elif [[ $NUMBER -lt 61 ]]
    then
        echo "G:$NUMBER"
    else
        echo "O:$NUMBER"
    fi
    

Command Execution and Process Control

  • Command separation: Use semicolon (;) to run multiple commands on a single line.

    • Commands execute sequentially from left to right
    • Each command's exit status can be checked individually
    bash
    [[ 4 -ge 5 ]]; echo $?
    ls -l; echo "Done"
    
  • Exit status: Every command has an exit status that indicates success or failure.

    • Access exit status of the last command with $?
    • Exit status 0 means success (true/no errors)
    • Any non-zero exit status means failure (false/errors occurred)
    • Common error codes: 127 (command not found), 1 (general error)
    bash
    echo $?
    [[ 4 -le 5 ]]; echo $?
    ls; echo $?
    bad_command; echo $?
    
  • Subshells and command substitution: Different uses of parentheses for execution contexts.

    • Single parentheses ( ... ) create a subshell
    • $( ... ) performs command substitution
    • Subshells run in separate environments and don't affect parent shell variables
    bash
    ( cd /tmp; echo "Current dir: $(pwd)" )
    current_date=$(date)
    file_count=$(ls | wc -l)
    echo "Today is $current_date"
    echo "Found $file_count files"
    
  • Sleep command: Pause script execution for a specified number of seconds.

    • Useful for creating delays in scripts
    • Can be used with decimal values for subsecond delays
    bash
    sleep 3
    sleep 0.5
    sleep 1
    

Loops

  • While loops: Execute code repeatedly while a condition is true.

    • Syntax: while [[ CONDITION ]] do STATEMENTS done
    bash
    I=5
    while [[ $I -ge 0 ]]
    do
        echo $I
        (( I-- ))
        sleep 1
    done
    
  • Until loops: Execute code repeatedly until a condition becomes true.

    • Syntax: until [[ CONDITION ]] do STATEMENTS done
    bash
    until [[ $QUESTION =~ \?$ ]]
    do
        echo "Please enter a question ending with ?"
        read QUESTION
    done
    until [[ $QUESTION =~ \?$ ]]
    do
        GET_FORTUNE again
    done
    
  • For loops: Iterate through arrays or lists using for loops with do and done to define the loop's logical block.

    bash
    for server in "${servers[@]}"
    do
        echo "Processing $server"
    done
    for (( i = 1; i <= 5; i++ ))
    do
        echo "Number: $i"
    done
    for (( i = 5; i >= 1; i-- ))
    do
        echo "Countdown: $i"
    done
    for i in {1..5}
    do
        echo "Count: $i"
    done
    

Arrays

  • Arrays: Store multiple values in a single variable.

    • Create arrays with parentheses: ARRAY=("value1" "value2" "value3")
    • Access elements by index: ${ARRAY[0]}, ${ARRAY[1]}
    • Access all elements: ${ARRAY[@]} or ${ARRAY[*]}
    • Array indexing starts at 0
    bash
    RESPONSES=("Yes" "No" "Maybe" "Ask again later")
    echo ${RESPONSES[0]}     # Yes          
    echo ${RESPONSES[1]}     # No         
    echo ${RESPONSES[5]}     # Index 5 doesn't exist; empty string              
    echo ${RESPONSES[@]}     # Yes No Maybe Ask again later   
    echo ${RESPONSES[*]}     # Yes No Maybe Ask again later 
    
  • Array inspection with declare: Use declare -p to view array details.

    • Shows the array type with -a flag
    • Displays all array elements and their structure
    bash
    ARR=("a" "b" "c")
    declare -p ARR # ARR=([0]="a" [1]="b" [2]="c")
    
  • Array expansion: Use "${array_name[@]}" syntax to expand an array into individual elements.

bash
for server in "${servers[@]}"

Functions

  • Functions: Create reusable blocks of code.

    • Define with FUNCTION_NAME() { STATEMENTS }
    • Call by using the function name
    • Can accept arguments accessible as $1, $2, etc.
    bash
    GET_FORTUNE() {
        echo "Ask a question:"
        read QUESTION
    }
    GET_FORTUNE
    
  • Function arguments: Functions can accept arguments just like scripts.

    • Arguments are passed when calling the function
    • Access arguments inside function using $1, $2, etc.
    • Use conditional logic to handle different arguments
    bash
    GET_FORTUNE() {
        if [[ ! $1 ]]
        then
            echo "Ask a yes or no question:"
        else
            echo "Try again. Make sure it ends with a question mark:"
        fi
        read QUESTION
    }
    GET_FORTUNE
    GET_FORTUNE again
    

Random Numbers and Mathematical Operations

  • Random numbers: Generate random values using the $RANDOM variable.

    • $RANDOM generates numbers between 0 and 32767
    • Use modulo operator to limit range: $RANDOM % 75
    • Add 1 to avoid zero: $(( RANDOM % 75 + 1 ))
    • Must use $(( ... )) syntax for calculations with $RANDOM
    bash
    NUMBER=$(( RANDOM % 6 ))
    DICE=$(( RANDOM % 6 + 1 ))
    BINGO=$(( RANDOM % 75 + 1 ))
    echo $(( RANDOM % 10 ))
    
  • Random array access: Use random numbers to access array elements randomly.

    • Generate random index within array bounds
    • Use random index to access array elements
    • Useful for random selections from predefined options
    bash
    RESPONSES=("Yes" "No" "Maybe" "Outlook good" "Don't count on it" "Ask again later")
    N=$(( RANDOM % 6 ))
    echo ${RESPONSES[$N]}
    
  • Modulo operator: Use % to get the remainder of division operations.

    • Essential for limiting random number ranges
    • Works with $RANDOM to create bounded random values
    • RANDOM % n gives numbers from 0 to n-1
    bash
    echo $(( 15 % 4 ))
    echo $(( RANDOM % 100 ))
    echo $(( RANDOM % 10 + 1 ))
    

Environment and System Information

  • Environment variables: Predefined variables available in the shell environment.

    • $RANDOM: Generates random numbers between 0 and 32767
    • $LANG: System language setting
    • $HOME: User's home directory path
    • $PATH: Directories searched for executable commands
    • View all with printenv or declare -p
    bash
    echo $RANDOM
    echo $HOME
    echo $LANG
    printenv
    
  • Variable inspection: Use declare to view and work with variables.

    • declare -p: Print all variables and their values
    • declare -p VARIABLE: Print specific variable details
    • Shows variable type (string, array, etc.) and attributes
    bash
    declare -p
    declare -p RANDOM
    declare -p MY_ARRAY
    
  • Command types: Different categories of commands available in bash.

    • Built-in commands: Executed directly by the shell (e.g., echo, read, if)
    • External commands: Binary files in system directories (e.g., ls, sleep, bash)
    • Shell keywords: Language constructs (e.g., then, do, done)
    • Use type <command> to see what type a command is
    bash
    type echo
    type ls
    type if
    type ./script.sh
    

File Creation and Management

  • File creation: Use touch to create new empty files.

    • Creates a new file if it doesn't exist
    • Updates the timestamp if the file already exists
    • Commonly used to create script files before editing
    bash
    touch script.sh
    touch bingo.sh
    touch filename.txt
    

Creating and Running Bash Scripts

  • Script execution methods: Multiple ways to run bash scripts:
    • sh scriptname.sh: Run with the sh shell interpreter.
    • bash scriptname.sh: Run with the bash shell interpreter.
    • ./scriptname.sh: Execute directly (requires executable permissions).
bash
sh questionnaire.sh
bash questionnaire.sh
./questionnaire.sh

File Permissions and Script Execution

  • Permission denied error: When using ./scriptname.sh, you may get "permission denied" if the file lacks executable permissions.

  • Checking permissions: Use ls -l to view file permissions.

    bash
    ls -l questionnaire.sh
    
  • Permission format: The output shows permissions as -rw-r--r-- where:

    • First character (-): File type (- for regular file, d for directory)
    • Next 9 characters: Permissions for owner, group, and others
    • r = read, w = write, x = execute
  • Adding executable permissions: Use chmod +x to give executable permissions to everyone.

    bash
    chmod +x questionnaire.sh
    
  • Script organization: Best practices for structuring bash scripts.

    • Start with shebang (#!/bin/bash)
    • Add descriptive comments about script purpose
    • Define variables at the top
    • Group related functions together
    • Main script logic at the bottom
    bash
    #!/bin/bash
    NAME="value"
    ARRAY=("item1" "item2")
    my_function() {
        echo "Function code here"
    }
    my_function
    echo "Script complete"
    
  • Sequential script execution: Create master scripts that run multiple programs in sequence.

    • Useful for automating workflows that involve multiple scripts
    • Each script runs to completion before the next one starts
    • Can combine different programs into a single execution flow
    • Arguments can be passed to individual scripts as needed
    • Can include different types of programs (interactive, automated, etc.)
    bash
    #!/bin/bash
    ./setup.sh
    ./interactive.sh
    ./processing.sh
    ./cleanup.sh
    

--assignment--

Review the Bash Scripting topics and concepts.