Bash Scripting Course

repository·main·Indexed 20 days ago

https://github.com/bahamas10/bash-course

A comprehensive educational resource for learning Bash scripting, ranging from beginner to advanced techniques. The course covers shell fundamentals, REPL concepts, file and directory operations, grep, pagers, man pages, environment variables, and command substitution. Designed to be OS-agnostic, it demonstrates functionality across Linux, Mac, and illumos.

Tokens
24.2K
Snippets
140
Records
149
Agent score
70%

What's inside bahamas10-bash-course

  1. Overview of the Bash Scripting Course

    main

    This course is designed to teach users how to become comfortable writing scripts in the shell. While the primary target is bash, the course content aims to be OS-agnostic, demonstrating the differences between Linux, Mac, and illumos to clarify where Bash functionality ends and operating system distribution begins.

    Prerequisites: Users are expected to have a basic understanding of programming concepts, such as variable assignment.

    Resources:

  2. Explore the repository structure

    main

    The repository is organized into several directories containing course materials, notes, and supporting tools:

    • foo/: Contains the foo directory created step-by-step during the course.
    • notes/: Contains organized notes and code snippets corresponding to each section of the course.
    • tools/: Contains tools utilized during the creation of the course content.
    • website/: Contains the scripts used to build and maintain the course.ysap.sh website.
  3. Use cut and tr for text manipulation

    main

    The cut and tr commands are used for basic text processing and transformation in Bash:

    • cut: Used to extract specific sections (columns, characters, or fields) from each line of a file or input.
    • tr (translate): Used for translating, deleting, or squeezing characters from standard input.
  4. Why standard aliases do not support arguments

    main
    In Bash, standard alias definitions do not support positional arguments (like $1, $2). When you define an alias like alias foo='echo $1', the $1 is not interpreted as an argument passed to the alias at runtime; instead, it is treated as a literal string or an empty variable depending on the context. To achieve functionality where a command accepts arguments and uses them within the command string, you must use a Bash Function instead of an alias.
  5. Check the exit status of the last command using $?

    main

    In Bash, the special variable $? stores the exit status of the most recently executed command. An exit status of 0 typically indicates success, while any non-zero value indicates an error or a specific exit code defined by the command.

    echo hi
    echo $?
    
    # If grep fails to find a match, it returns a non-zero status
    echo hi | grep bye
    echo $?
  6. Understand the difference between $* and $@ expansion

    main

    When expanding positional parameters or arrays, the choice between * and @ determines how the items are treated:

    • * (and $* / ${arr[*]}): Joins all items together into a single string, using the first character of $IFS (Internal Field Separator) as the delimiter.
    • @ (and $@ / ${arr[@]}): Deconstructs the array/parameters into individual elements, preserving the exact form of the array.

    Crucial Best Practice: Always use double quotes (e.g., "$@" or "${arr[@]}") to prevent word-splitting and globbing issues. If your logic works without quotes, you are likely handling data incorrectly.

    # Joins items into one string
    for arg in $*; do
        echo "<$arg>"
    done
    
    # Deconstructs into individual elements (Preferred)
    for arg in "$@"; do
        echo "<$arg>"
    done
  7. Check if a file descriptor is a TTY

    main

    In Bash, you can determine if a file descriptor (like stdout or stdin) is connected to a terminal (TTY) using the [[ -t <fd> ]] test operator. This is useful for deciding whether to output colored text, interactive prompts, or formatted tables, which might look broken when piped to another command or a file.

    • [[ -t 1 ]] checks if stdout is a terminal.
    • [[ -t 0 ]] checks if stdin is a terminal.

    If the condition is true, the descriptor is a terminal; otherwise, it is a pipe, a file, or another non-TTY device.

    #!/usr/bin/env bash
    if [[ -t 1 ]]; then
      echo stdout is a terminal
    else
      echo stdout is NOT a terminal
    fi
  8. Distinguish between Brace Expansion and Globbing

    main

    It is critical to understand the difference between Brace Expansion and Globbing (wildcards):

    1. Brace Expansion ({}): Generates strings based on the pattern provided. It does not check if the files exist. If you expand files/{foo,bar}.txt, the shell produces those two strings regardless of whether the files are on disk.
    2. Globbing (*, ?, []): Matches existing files on the filesystem. If no files match the pattern, the shell (by default) leaves the pattern as a literal string or returns an error depending on shell settings.
    3. Extended Globbing (@(...)): Requires specific shell options (like extglob in Bash) to match specific patterns against existing files.
    # Brace expansion: produces strings even if files don't exist
    printf '<%s>\n' files/{foo,bar}.txt
    
    # Extended globbing: matches existing files matching foo OR bar
    printf '<%s>\n' files/@(foo|bar).txt
  9. Compare `less` and `more` pagers

    main

    Both less and more are used to paginate text, but less is generally more powerful. You can locate these utilities on your system using ls -1i to see their inode numbers and paths.

    Common usage patterns:

    • less file.txt (Direct file viewing)
    • cat file.txt | less (Piping content to a pager)
    • cat ... | grep ... | less (Piping filtered content to a pager)
    ls -1i /usr/bin/more /usr/bin/less