Title: Bash Scripting For Automation — LearnCoachAssist

Q: What is Bash?
A: Bash (Bourne Again SHell) is a Unix shell and command language written as a free software replacement for the Bourne shell (sh). It is the default login shell on most Linux distributions and macOS (until Catalina).

Q: What file extension is conventionally used for Bash scripts?
A: .sh. While not strictly required for execution, .sh signals intent and lets tooling treat the file as a shell script.

Q: What must the first line of an executable Bash script be?
A: A shebang line, e.g. #!/usr/bin/env bash or #!/bin/bash, which tells the kernel which interpreter to invoke.

Q: What command makes a script file executable?
A: chmod +x script.sh (or chmod 755 script.sh).

Q: How do you run a script located in the current directory?
A: ./script.sh. The dot-slash is required because the current directory is not normally in $PATH.

Q: What is the difference between sh script.sh and ./script.sh?
A: sh explicitly invokes the sh interpreter and ignores the shebang, so Bash-specific features may break. ./script.sh honors the shebang and uses the listed interpreter.

Q: What is a variable in Bash?
A: A named storage location for a value, assigned with NAME=value (no spaces around =) and referenced as $NAME or ${NAME}.

Q: How do you make a variable available to child processes?
A: Export it: export VAR=value or VAR=value; export VAR. Without export, the variable is local to the current shell.

Q: What is the difference between $VAR and ${VAR}?
A: Both expand the value, but ${VAR} disambiguates boundaries, e.g. ${VAR}suffix vs the ambiguous $VARsuffix. It also enables parameter expansion features like default values and substring operations.

Q: How do you provide a default value when expanding an unset variable?
A: ${VAR:-default} substitutes default if VAR is unset or empty. ${VAR:=default} also assigns the default back to VAR.

Q: What does ${VAR:?message} do?
A: Prints message to stderr and exits the script with status 1 if VAR is unset or empty. Useful for required-input guards.

Q: What are positional parameters?
A: The arguments passed to a script or function, accessed as $1, $2, ..., with $0 being the script name and $# the count of arguments.

Q: What does "$@" expand to?
A: Each positional parameter as a separate, individually quoted word: "$1" "$2" "$3" .... This is the correct way to forward arguments.

Q: What is the difference between "$@" and "$*"?
A: "$@" expands to separate quoted words preserving argument boundaries. "$*" joins all arguments into a single word separated by the first character of IFS (a space by default). Always prefer "$@" for iteration.

Q: How do you get the exit status of the last command?
A: The special variable $? holds it. Zero means success; non-zero indicates failure.

Q: What are some standard exit codes used in Bash?
A: 0 success, 1 general error, 2 misuse of shell builtin, 126 command found but not executable, 127 command not found, 128+N terminated by signal N (e.g. 130 = SIGINT/Ctrl-C, 137 = SIGKILL, 143 = SIGTERM).

Q: What does set -e do?
A: Tells the shell to exit immediately if any command, pipeline, or simple command exits with a non-zero status (unless explicitly tested in if/while/||/&& contexts).

Q: What is the purpose of set -u?
A: Treats unset variables as an error when expanded, causing immediate exit. Helps catch typos and missing configuration.

Q: What does set -o pipefail do?
A: Makes a pipeline's return status the value of the rightmost command to exit non-zero (or zero if all succeed), instead of the last command only. Combined with set -e it surfaces failures hidden mid-pipeline.

Q: What is a recommended strict-mode prologue for Bash scripts?
A: set -euo pipefail — exit on error, undefined variables, and pipeline failures. Often paired with IFS=$'\n\t' to avoid word-splitting surprises.

Q: What is the IFS variable?
A: Internal Field Separator: the characters Bash uses for word splitting after unquoted expansions and for splitting records in read. Default is space, tab, newline.

Q: What is word splitting?
A: After unquoted parameter, command, and arithmetic expansions, Bash splits the result into words on each character in IFS. Always quote expansions ("$var") to prevent it.

Q: What is globbing in Bash?
A: Filename pattern expansion: unquoted *, ?, [...] match filenames in the current directory. To disable, set -f; to force, set -f; set +f in a subshell.

Q: How do you prevent globbing from matching nothing and producing a literal pattern?
A: set -u does not affect this, but shopt -s nullglob makes empty globs expand to nothing, and shopt -s failglob causes the command to fail when no match is found.

Q: What is the difference between single and double quotes in Bash?
A: Single quotes preserve every character literally; no expansion occurs. Double quotes preserve most characters but allow $, backticks, \\, and ! (history) to expand. Always double-quote variables.

Q: How do you write a multi-line string in Bash?
A: Use a here-document: cat <<EOF\nline 1\nline 2\nEOF. Quote the delimiter (<<'EOF') to disable parameter expansion inside.

Q: What is a here-string and how is it used?
A: command <<< "$variable" feeds the variable's value as the command's standard input, useful for piping single values without echo var | cmd.

Q: What are the basic conditional expressions in an if statement?
A: if, elif, else, fi. The condition is a list of commands; its exit status (0 = true) decides the branch.

Q: What is the difference between [ ], [[ ]], and (( ))?
A: [ ] is the POSIX test builtin with word-splitting. [[ ]] is a Bash keyword: no word-splitting on operands, supports == glob and =~ regex. (( )) evaluates arithmetic, returning 0 when the result is non-zero.

Q: What are common file-test operators in [[ ]]?
A: -e exists, -f is regular file, -d is directory, -L is symlink, -r readable, -w writable, -x executable, -s size > 0, ! negates. Example: [[ -f "$file" ]].

Q: What are common string-test operators?
A: [[ -z "$s" ]] true if empty, -n true if non-empty, == or = equal (with glob on right), != not equal, < and > lexicographic compare.

Q: How do you test two integers in Bash?
A: Use (( a == b )), (( a < b )), etc. Inside [[ ]] the operators are -eq, -ne, -lt, -le, -gt, -ge. Do not use </> on integers in [[ ]]; they do lexicographic compare.

Q: What is a case statement used for?
A: Pattern-matching branching over a single value, e.g. case "$x" in\n start) ... ;;\n stop|halt) ... ;;\n *) default ;;\nesac. The right-hand side supports globs and | alternations.

Q: How do you write a for loop over a list of values?
A: for f in a b c; do echo "$f"; done. The list can come from a glob, command substitution, or array.

Q: How do you loop over an array safely?
A: for item in "${arr[@]}"; do echo "$item"; done. Quoting and [@] preserve elements that contain spaces.

Q: What is the C-style for loop syntax?
A: for (( i=0; i<10; i++ )); do echo "$i"; done. Uses arithmetic expression syntax with comma-separated C-style clauses.

Q: What is the syntax for a while loop?
A: while condition; do body; done. The condition is re-evaluated after each iteration; the loop ends when the command returns non-zero.

Q: What does until do?
A: Loops as long as its condition is false: until ping -c1 host; do sleep 5; done.

Q: How do you break out of a loop early or skip an iteration?
A: break exits the innermost loop; continue skips to the next iteration. Both accept an optional integer level, e.g. break 2 exits two levels.

Q: How do you define a Bash function?
A: name() { commands; } or function name { commands; }. The body shares the caller's shell environment (no local scope by default).

Q: How do you make a variable local to a function?
A: Use the local builtin: local foo=bar. Without it, assignments are global.

Q: How do you pass arguments to a function?
A: Positional parameters $1, $2, etc. inside the function body. Quoted arrays can be passed by reference via declare -n refname=array (Bash 4.3+).

Q: What is command substitution?
A: Using the output of a command as a value: $(command) (preferred) or the legacy backticks `command`. $(...) nests cleanly and is recommended.

Q: What is process substitution?
A: <(cmd) and >(cmd) expose a command's input or output as a filename referring to a /dev/fd/N pipe. Example: diff <(sort a) <(sort b).

Q: What is an arithmetic expansion?
A: $(( expression )) evaluates an integer expression, e.g. $(( a + b * 2 )). Supports +, -, *, /, %, ** (power), bitwise, and ternary.

Q: How do you define an indexed array?
A: arr=(one two three) or arr[0]=one; arr[1]=two. Access with ${arr[0]}, all elements with ${arr[@]} or ${arr[*]}, count with ${#arr[@]}.

Q: How do you append to an array?
A: arr+=(four five). To append a single element: arr+=("six").

Q: How do you loop over array indices and values?
A: for i in "${!arr[@]}"; do echo "$i=${arr[i]}"; done. ${!arr[@]} expands to the indices of arr.

Q: How do you define an associative array (hash/dict)?
A: declare -A m=([key1]=val1 [key2]=val2). Requires Bash 4+. Access with ${m[key1]}, all keys with ${!m[@]}, length with ${#m[@]}.

Q: How do you get the length of a string?
A: ${#var} returns the number of characters. For an array, use ${#arr[@]} for the number of elements.

Q: How do you do substring or slice operations?
A: ${var:offset:length}. Example: ${path:0:5} gets the first 5 chars. Negative offsets are counted from the end.

Q: How do you remove a prefix or suffix pattern from a variable?
A: ${var#pattern} removes shortest prefix, ${var##pattern} removes longest prefix, ${var%suffix} removes shortest suffix, ${var%%suffix} removes longest suffix.

Q: How do you replace text in a variable's value?
A: ${var/old/new} replaces first match, ${var//old/new} replaces all, ${var/#old/new} replaces at the start, ${var/%old/new} at the end.

Q: How do you convert a string to upper or lower case?
A: Bash 4+: ${var^^} to upper, ${var,,} to lower. ${var^} and ${var,} capitalize/decapitalize the first character only.

Q: How do you read a line of input from the user?
A: read -rp "Prompt: " answer. -r disables backslash escaping, -p provides a prompt.

Q: How do you read a file line by line?
A: while IFS= read -r line; do echo "$line"; done < file.txt. Setting IFS= preserves leading/trailing whitespace.

Q: How do you read fields separated by a delimiter into variables?
A: IFS=: read -r user _ uid _ _ home _ < /etc/passwd. The second positional is a placeholder variable name to skip fields.

Q: What is /dev/null used for in scripts?
A: Discarding output: cmd > /dev/null 2>&1 silences both stdout and stderr. Useful when only the exit code matters.

Q: How do you redirect stdout and stderr separately?
A: cmd > out.log 2> err.log. 2>&1 sends stderr to wherever stdout points (order matters: do redirections left to right).

Q: How do you append redirection?
A: cmd >> log.txt 2>&1. Without >>, > truncates the file each run.

Q: What does exec do in a script?
A: Without redirection it replaces the current shell process with a new command. With redirection (exec > file) it modifies the current shell's file descriptors, e.g. to send all subsequent output to a log.

Q: What is a subshell?
A: A child shell spawned with ( commands ) or by backgrounding. Changes to variables, cd, and shell options do not affect the parent. Useful for isolating cd and temporary variable changes.

Q: How do you run a command in the background?
A: Append &: long_job &. The shell prints the job ID and PID. Use wait %1 or wait $pid to synchronize.

Q: What does trap do?
A: Sets a handler to run when the shell receives a signal or exits. Example: trap 'rm -f "$tmpfile"' EXIT ensures cleanup on any exit, including signals.

Q: How do you run cleanup code whether the script succeeds or fails?
A: Use trap 'cleanup' EXIT. The EXIT pseudo-signal fires on any termination: normal exit, error, or signal (except SIGKILL).

Q: What is the mktemp command for?
A: Creates a unique temporary file or directory safely: tmp=$(mktemp) or tmpd=$(mktemp -d). Avoids race conditions and predictable paths in /tmp.

Q: What is the difference between source script.sh and ./script.sh?
A: source (alias: .) executes the file in the current shell, so variable assignments and cd persist. ./script.sh runs in a new subshell, so its changes do not affect the parent.

Q: What is the getopts builtin used for?
A: Parsing short command-line options like -a, -b value. Example: while getopts "ab:c" opt; do case $opt in ... esac; done. OPTARG holds an option's argument; $OPTIND is the next index to process.

Q: What is a common pitfall when reading getopts after the loop?
A: You usually want to shift processed options with shift $((OPTIND-1)) so that "$@" contains the remaining positional arguments.

Q: How do you check whether a command exists before calling it?
A: command -v cmd >/dev/null 2>&1 (preferred) or which cmd. Use it in an if to gate behaviour: if command -v docker >/dev/null; then ....

Q: What is the difference between $(cmd) and `cmd`?
A: Both perform command substitution. $(...) is the modern form: easier to read, supports nesting ($(echo $(date))), and behaves more predictably inside double quotes.

Q: What does the local builtin do?
A: Declares a variable with function-local scope, hiding any global of the same name. Always use local for variables inside functions to avoid leaking values.

Q: What is declare -i used for?
A: Forces a variable to integer type: arithmetic is performed on assignment, e.g. declare -i n=1+2 gives n=3. Useful for counters, though ((n++)) is often clearer.

Q: What is declare -r?
A: Makes a variable read-only: any later assignment is an error. Equivalent to the readonly builtin, e.g. declare -r VERSION="1.0".

Q: What is the difference between echo and printf?
A: echo adds a trailing newline and may interpret backslash escapes depending on the shell. printf is portable, format-driven, and gives precise control. Prefer printf '%s\\n' "$var" for arbitrary data.

Q: How do you print to stderr from a script?
A: printf '%s\\n' "error" >&2 or echo "error" >&2. Send errors to stderr so they can be redirected separately from normal output.

Q: What is the read builtin with -d?
A: -d DELIM sets the line delimiter instead of newline, useful for reading records terminated by NUL (read -d '') in find -print0 loops.

Q: What is the find command's -print0 for?
A: Prints filenames separated by a NUL byte so filenames with spaces or newlines are unambiguous. Pair with xargs -0 or while IFS= read -r -d '' f; do ...; done.

Q: What is the xargs command for?
A: Builds and executes command lines from standard input. Safer: xargs -0 -n 1 -I {} cmd {} for NUL-delimited input and one argument per invocation.

Q: How do you use find to delete files older than 7 days?
A: find /path -type f -mtime +7 -delete. Test first by removing -delete to list matches. -mtime +7 means strictly more than 7×24 hours old.

Q: What is a heredoc with command substitution?
A: cat <<EOF > out.txt\nHello $USER\nEOF. The unquoted delimiter allows $USER to expand. Use <<'EOF' to disable expansion entirely.

Q: How do you run a command and capture both stdout and stderr?
A: out=$(cmd 2>&1) or out=$(cmd 2>&1; echo "rc=$?"). For preserving them separately, use temp files: cmd >out 2>err.

Q: What is the purpose of set -x or set -o xtrace?
A: Prints each command to stderr (after expansion) before executing it. Great for debugging; turn off with set +x.

Q: What is PS4 in Bash?
A: The prompt prefix used by set -x for trace output. Setting PS4='+ ${BASH_SOURCE}:${LINENO}: ' gives line-numbered traces that pinpoint where in a script each command runs.

Q: How do you time how long a piece of code takes?
A: Use time: time cmd, or TIMEFORMAT='%R'; time { cmd1; cmd2; } to get the elapsed seconds in ${TIMEFORMAT}-aware contexts. Inside a script, SECONDS=0; cmd; echo "$SECONDS" gives elapsed seconds.

Q: What is a common Bash scripting pitfall involving spaces?
A: VAR = value is a syntax error or runs the command VAR with args = and value. Whitespace around = in assignments is not allowed.

Q: What goes wrong with if [ $foo = "bar" ] when foo is empty?
A: Word-splitting expands it to [ = "bar" ], a syntax error. Always quote: if [ "$foo" = "bar" ] or use [[ "$foo" == "bar" ]].

Q: Why should you avoid parsing ls output in scripts?
A: Filenames can contain spaces, newlines, or quotes that break naive parsing. Use globs (for f in *.txt) or find -print0 with xargs -0 or read -d ''.

Q: What is the issue with for f in $(ls)?
A: Triggers word splitting and glob expansion on each filename, mangling names with spaces or special characters. Prefer for f in * or find -print0 | while read -d '' f.

Q: What is the best way to count lines in a file?
A: wc -l < file.txt to avoid the filename in output, or awk 'END{print NR}' file for portability across line endings. grep -c '' file also counts newlines.

Q: How do you iterate over command-line arguments?
A: for arg in "$@"; do echo "$arg"; done. Quoting "$@" preserves arguments containing spaces.

Q: How do you join an array into a single string with a delimiter?
A: joined=$(IFS=,; echo "${arr[*]}") or in Bash 4.4+ joined="${arr[*]}" with IFS=, set locally. For arbitrary joining use printf '%s\\n' "${arr[@]}" | paste -sd ,.

Q: What is the null byte and how does Bash handle it?
A: The null byte (\\0) cannot appear in Bash strings, since C-style null terminators end strings. find -print0 works around this for filenames; never printf a NUL into a Bash variable.

Q: How do you ensure a script is run with Bash and not sh?
A: Start with #!/usr/bin/env bash and check at runtime: [[ -n "${BASH_VERSION:-}" ]] || { echo "Need bash"; exit 1; }.

Q: What is the difference between $0 and ${BASH_SOURCE[0]}?
A: $0 is the name used to invoke the script (may be bash, ./script.sh, or just script.sh). ${BASH_SOURCE[0]} is always the path of the script file currently executing, useful for resolving the script's own directory: dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd).

Q: How do you read a configuration file as Bash variables?
A: source config.sh or . config.sh. Files meant for sourcing should not run side effects and should be careful with quoting.

Q: How do you include another script without executing it?
A: There is no direct include: use source (executes) or parse functions with eval "$(declare -f funcname)". Modules are usually sourced.

Q: What is a common cause of "Argument list too long" errors?
A: Passing the expanded form of a huge glob directly to a command, e.g. rm * in a directory with millions of files. Use find ... -exec rm {} + or xargs instead.

Q: What is a Bash subshell trap?
A: (cd /tmp && cmd) changes directory only in the subshell; the parent's working directory is unchanged once the subshell exits.

Q: How do you convert a string to an integer safely?
A: Use arithmetic: n=$((10#$s)) forces base-10 interpretation and errors on non-digits. declare -i n=$s also forces integer semantics but silently ignores bad suffixes.

Q: What is the difference between return and exit in a function?
A: return N exits the function with status N (default: the last command's status). exit N terminates the entire script with status N.

Q: How do you make a script only run on Linux, not macOS?
A: case "$(uname -s)" in Linux) ;; *) echo "Linux only"; exit 1 ;; esac. Or use [[ "$(uname)" == "Linux" ]] with a guard.

Q: How do you schedule a Bash script to run periodically?
A: Use cron (crontab -e, e.g. 0 3 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1) or systemd timers. Cron jobs have a minimal PATH; set required variables explicitly.

Q: What is a Bash strict-mode issue with cd?
A: set -e doesn't help if cd succeeds in the parent but a later command fails for another reason. Use cd /path || exit 1 or pushd /path || exit to make failure visible.

Q: How do you check whether you are running as root?
A: [[ $EUID -eq 0 ]] (root has EUID 0). Alternatively, [[ "$(id -u)" -eq 0 ]]. Use this to gate operations needing privileges.

Q: What is the BASH_ENV variable?
A: A file sourced by non-interactive Bash scripts on startup. Useful for setting strict mode and common aliases across all scripts: export BASH_ENV=/etc/bash_env.sh.

Q: How do you make a script portable across Linux distributions?
A: Avoid Bash 4+ features when targeting older systems, use #!/bin/sh if POSIX is enough, and test on the target. Use command -v instead of which and prefer printf to echo.

Q: How do you debug a script that exits early under set -e?
A: Add set -x for tracing, run with bash -x script.sh, or temporarily disable set -e for a block. bash -n script.sh checks syntax without running.

Q: What is the difference between . script and source script?
A: They are identical. source is a Bash alias for the POSIX dot operator ..

Q: What is the effect of shopt -s expand_aliases?
A: Enables alias expansion in non-interactive scripts. By default aliases are not expanded in scripts, so the line alias ll='ls -la' defined in ~/.bashrc won't apply.

Q: How do you test a script safely?
A: Use bash -n for syntax, shellcheck script.sh (linter) for issues, and run with set -x on a copy or in a sandbox. For destructive commands, dry-run with echo prefixed or use rm -i during testing.

Q: What is ShellCheck?
A: A static analysis tool (shellcheck.net) that flags common bugs, quoting issues, and style problems in shell scripts. It is highly recommended; install via package manager and run in CI.

Q: How do you handle a long-running command with a timeout?
A: Use timeout 30s cmd from coreutils, returning non-zero on timeout. In pure Bash: ( sleep 30; kill $$ ) & watcher=$!; cmd; kill $watcher 2>/dev/null.

Q: What is the basename and dirname pair?
A: basename /a/b/c.sh prints c.sh, dirname /a/b/c.sh prints /a/b. Useful for working with file paths inside scripts.

Q: How do you check if a string matches a regex in Bash?
A: [[ "$s" =~ ^[0-9]+$ ]] matches a digits-only string. Capture groups: if [[ "$s" =~ ^([A-Z]+)-([0-9]+)$ ]]; then echo "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}"; fi.

Q: What is the : builtin?
A: A no-op that ignores its arguments and returns 0. Used as a placeholder in empty functions or branches, and as the left side of parameter expansion tricks, e.g. : "${VAR:=default}".

Q: How do you log script output with timestamps?
A: exec > >(while IFS= read -r line; do printf '%s %s\\n' "$(date '+%F %T')" "$line"; done) 2>&1. Or pipe everything through ts '[%F %T]' from moreutils.

Q: How do you compare two floating-point numbers in Bash?
A: Bash arithmetic only handles integers. Use awk or bc: awk -v a=1.5 -v b=1.4 'BEGIN{exit !(a>b)}', or (( $(echo "$a > $b" | bc -l) )).

Q: What is the (( )) command?
A: An arithmetic-evaluation builtin returning 0 if the expression result is non-zero. Use it for integer tests: if (( a < b )); then ...; fi.

Q: What is the shopt builtin for?
A: Toggles optional shell behaviour. Examples: shopt -s nocaseglob makes globs case-insensitive, shopt -s dotglob includes hidden files in globs, shopt -s globstar enables ** for recursive matching.