Skip to content

Top 50 Shell Scripting Interview Questions

The most frequently asked questions in DevOps, SRE, backend, and Linux admin interviews.


Essentials (Questions 1–15)

1. What is bash and how does it differ from sh?

Show answer

bash (Bourne Again SHell) is a superset of sh (POSIX shell). bash adds arrays, [](<#>), (( )), process substitution, {a..z} brace expansion, and many other features not in POSIX sh. Scripts starting with #!/bin/sh should use only POSIX features for portability.

2. What is a shebang line?

Show answer

The first line of a script: #!/usr/bin/env bash. The #! tells the kernel which interpreter to use. #!/usr/bin/env bash searches $PATH for bash (portable). #!/bin/bash hardcodes the path (less portable).

3. What does set -euo pipefail do?

Show answer

-e: exit on error. -u: error on unset variables. -o pipefail: pipeline fails if any command fails. Best practice for production scripts.

4. How do you pass arguments to a script?

Show answer

Arguments appear after the script name: ./script.sh arg1 arg2. Inside the script: $1, $2, etc. $# is the count. $@ is all arguments (individually quoted). $0 is the script name.

5. What is the difference between $@ and $*?

Show answer

"$@" expands to separate quoted words. "$*" expands to one string. Use "$@" when passing arguments to preserve values containing spaces.

6. How do you check if a file exists?

Show answer

[[ -f "$file" ]] — exists and is a regular file. [[ -e "$file" ]] — exists (any type). [[ -d "$dir" ]] — exists and is a directory.

7. What is $? and when would you use it?

Show answer

Exit status of the last command. 0 = success, non-zero = failure. Useful for conditional logic: cmd; if [[ $? -ne 0 ]]; then .... More idiomatically: if ! cmd; then ....

8. What is the difference between > and >>?

Show answer

> overwrites (truncates to zero before writing). >> appends. Both create the file if it does not exist.

9. How do you run a script in the background?

Show answer

Append &: ./script.sh &. This runs it in a background subshell. Capture its PID: ./script.sh &; PID=$!. Wait for it: wait $PID.

10. What does chmod +x do?

Show answer

Adds the execute bit for all three categories (user, group, other). Without it, ./script.sh gives "Permission denied." Equivalent to chmod a+x.

11. What is a subshell?

Show answer

A child process that inherits the parent shell's variables but cannot modify the parent's environment. Created by (commands), pipelines, and command substitution $(cmd). Variables set in a subshell are not visible in the parent.

12. How do you read user input in a script?

Show answer

read -r variable reads one line. -p "Prompt: " shows a prompt. -s hides input (for passwords). -t N sets a timeout. Always use -r to prevent backslash interpretation.

13. How do you define a function in bash?

Show answer

my_func() { commands; } — POSIX compatible. Or function my_func { commands; } — bash-specific. Always use local for variables inside functions.

14. What is the difference between == and -eq?

Show answer

== compares strings: [[ "$a" == "$b" ]]. -eq compares integers: [[ "$a" -eq "$b" ]] or (( a == b )). Using -eq on strings or == on integers can give unexpected results.

15. What does source (or .) do?

Show answer

Runs a file in the current shell process — functions and variables defined in it become available in the current session. Contrast with bash file.sh which runs in a new subprocess.


Intermediate (Questions 16–35)

16. What is word splitting and when does it matter?

Show answer

Bash splits unquoted variable expansions on characters in $IFS (default: space, tab, newline). cmd $var where var="a b" passes two arguments. cmd "$var" passes one. Always quote variable references.

17. What is IFS and how do you use it?

Show answer

Internal Field Separator — the characters bash uses to split words. Default: whitespace. Override to split on other delimiters: IFS=',' read -ra fields <<< "a,b,c". Restore with IFS=$' \t\n' or unset IFS.

18. How do you create a temporary file safely?

Show answer

mktemp — creates a temp file with a unique name: TMPFILE=$(mktemp). For a directory: mktemp -d. Always clean up with trap 'rm -f "$TMPFILE"' EXIT.

19. What is a here document (<<EOF)?

Show answer

A way to pass multi-line input to a command: cat << EOF ... EOF. Variables expand unless the delimiter is quoted (<< 'EOF'). The closing delimiter must be at column 0.

20. How do you prevent a script from running twice simultaneously?

Show answer

Use a lock file: exec 9>/tmp/script.lock; flock -n 9 || exit 1. Or: flock -n /tmp/script.lock script.sh. The second instance detects the lock and exits.

21. What does trap do?

Show answer

Registers a command to run when a signal or event occurs. trap 'cleanup' EXIT — runs on any exit. trap 'handler' INT TERM — runs on Ctrl+C or kill.

22. How do you iterate over an array?

Show answer

for item in "${arr[@]}"; do ...; done. Always use double-quoted "${arr[@]}" to preserve elements containing spaces.

23. What is an associative array?

Show answer

An array with string keys instead of integer indices. Declare with declare -A map. Assign: map["key"]="value". Iterate keys: "${!map[@]}". Requires bash 4.0+.

24. How do you check if a string contains a substring?

Show answer

[[ "$str" == *"substring"* ]] — glob matching inside [](<#>). Or: [[ "$str" =~ substring ]] — regex. Or: echo "$str" | grep -q "substring".

25. What does ${var##*/} do?

Show answer

Removes the longest prefix matching */ — effectively extracting the basename from a path. /home/user/file.txtfile.txt.

26. How do you count the number of lines in a file without wc?

Show answer

awk 'END {print NR}' file.txtNR at END is the total line count.

27. What is the difference between && and || in shell?

Show answer

cmd1 && cmd2 — run cmd2 only if cmd1 succeeds (exit 0). cmd1 || cmd2 — run cmd2 only if cmd1 fails (non-zero). Common pattern: cd /path || exit 1.

28. How do you redirect both stdout and stderr to a file?

Show answer

command > file 2>&1 (POSIX). Or command &> file (bash shorthand). The order matters: 2>&1 > file is wrong — it redirects stderr to the terminal, then stdout to the file.

29. What is xargs and when do you use it?

Show answer

Builds and runs commands from stdin. find . -name "*.tmp" | xargs rm removes all found files. Use xargs -0 with find -print0 for filenames with spaces. Use -P N for parallel execution.

30. How do you find the 10 largest files in a directory tree?

Show answer

find /path -type f -printf "%s\t%p\n" | sort -rn | head -10 — or du -ah /path | sort -rh | head -10 for human-readable sizes.

31. What is eval and why should you avoid it?

Show answer

eval re-evaluates its arguments as a shell command. It is powerful but dangerous — if any part of the evaluated string comes from user input, it becomes a code injection vulnerability. Almost always there is a safer alternative using arrays, declare -n, or ${!var} indirect expansion.

32. How do you check if a command exists before using it?

Show answer

command -v cmd > /dev/null 2>&1 || die "cmd not found". Prefer command -v over which — it works for builtins, functions, and aliases too.

33. What is $PIPESTATUS?

Show answer

An array of exit codes for each command in the last pipeline. cmd1 | cmd2 | cmd3; echo ${PIPESTATUS[@]} prints three exit codes. Useful when set -o pipefail is not in effect.

34. How do you reverse the lines in a file?

Show answer

tac file.txt (GNU coreutils). Or tail -r file.txt (BSD/macOS). Or awk '{lines[NR]=$0} END {for(i=NR;i>0;i--) print lines[i]}' file.txt (portable).

35. What does 2>/dev/null do?

Show answer

Redirects stderr to /dev/null, discarding all error messages. /dev/null is a special file that discards everything written to it and returns EOF on read.


Advanced (Questions 36–50)

36. What is process substitution <(cmd)?

Show answer

Creates a temporary named pipe (FIFO) connected to the output of cmd. Used where a file argument is expected: diff <(sort a.txt) <(sort b.txt) diffs the sorted versions without creating temp files.

37. How do you send an email or notification from a cron job on failure?

Show answer

Cron mails stdout/stderr to the local user by default. For external notification: use curl to post to a Slack webhook or send via mail/sendmail in your script's error handler.

38. What is BASH_SOURCE and when do you need it?

Show answer

An array where ${BASH_SOURCE[0]} is the path of the currently executing file, even when sourced. Used to find a script's own directory: DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)". $0 gives the original script name, not the sourced file's path.

39. How do you make a script portable between bash and POSIX sh?

Show answer

Use #!/bin/sh. Avoid: [](<#>), (( )), {1..5}, arrays, declare, local (some sh), read -p, $'...', ${var,,}. Use POSIX alternatives: [ ], $(( )), seq, positional parameters, printf.

40. What is the difference between kill -9 and kill -15?

Show answer

kill -15 (SIGTERM) asks the process to terminate gracefully — it can catch the signal and clean up. kill -9 (SIGKILL) forces immediate termination by the kernel — the process cannot intercept it and has no chance to clean up. Always try SIGTERM first.

41. How do you run multiple commands in parallel in bash?

Show answer

Background them: cmd1 & cmd2 & wait. Use xargs -P N for parallel file processing. Or GNU parallel for more control. Capture exit codes: wait -n (bash 4.3+) waits for any background job.

42. What does exec > logfile 2>&1 do in a script?

Show answer

Replaces the script's stdout with logfile and stderr with stdout (the log). All subsequent output — including subcommands — goes to the log. The script continues executing; this is not the same as running a new process.

43. How do you test if a variable is an integer?

Show answer

[[ "$var" =~ ^-?[0-9]+$ ]] — matches an optional minus sign followed by one or more digits. Or: (( var + 0 )) 2>/dev/null — returns non-zero if not a number (but not safe for user input).

44. What is flock and when would you use it?

Show answer

flock acquires a POSIX advisory lock on a file. Used to prevent concurrent script execution: flock -n /tmp/app.lock script.sh. The lock is automatically released when the process exits or the file descriptor is closed.

45. How do you find and replace a string across multiple files?

Show answer

grep -rl "old" . | xargs sed -i 's/old/new/g' — find all files containing "old", then replace in each. On macOS: sed -i '' 's/old/new/g'. Or: find . -name "*.conf" -exec sed -i 's/old/new/g' {} +.

46. What is bats and why use it?

Show answer

Bash Automated Testing System — a test framework for bash scripts. Lets you write unit tests: @test "it greets" { run ./greet.sh Nikhil; assert_output "Hello, Nikhil!"; }. Run with bats test_file.bats. Important for any script others will depend on.

47. How do you handle unicode and non-ASCII filenames?

Show answer

Set LANG=en_US.UTF-8 (or your locale). Use LC_ALL=C temporarily for sorting if you need byte-order sorting. Avoid assumptions about character width. Quote all filenames. Use printf "%s\n" instead of echo for arbitrary strings.

48. What does declare -p var do?

Show answer

Prints the declaration of var in a form that can be re-executed: declare -- var="value" or declare -a arr=([0]="a" [1]="b"). Useful for inspecting variable type and value, especially for arrays.

49. What is the difference between exit and return in bash?

Show answer

exit N terminates the current shell process (or subshell). return N exits the current function (or sourced script). Using return outside a function/sourced script causes an error in some shells.

50. How would you design a script that is safe to run multiple times (idempotent)?

Show answer

Check state before acting: [[ -d "$dir" ]] || mkdir "$dir". Use cp -n (no-clobber) or rsync (which only copies changed files). For config: check if the line already exists before appending. Use --dry-run to preview. Ensure cleanup is also idempotent: rm -f never fails on missing files.


See also: week-01-review and week-02-review for topic-organized questions.