Bash & the POSIX Shell Module 2
How Bash reads a command line interview questions
Interview questions on how Bash reads a command line: short warm-ups, then what each harder question tests, the first step of a good answer and its follow-ups.
Warm-up questions
Short questions with short answers, each answered in full.
-
Fresher to mid
In what order does Bash expand a command line?
Answered in the lesson How Bash reads a line: tokens and expansions
-
Fresher to mid
How do single quotes, double quotes and $'...' differ in Bash?
Answered in the lesson Quoting: single, double, backslash and $'...'
-
Fresher to mid
Why should you write "$var" instead of $var in Bash?
Answered in the lesson Word splitting and IFS: why "$var" needs quotes
-
Fresher to mid
What happens in Bash when a glob matches no files?
Answered in the lesson Globbing: wildcards, dotfiles, extglob, globstar
-
Fresher to mid
Why does echo {1..$n} not print a range in Bash?
-
Fresher to mid
Why do shell scripts prefer printf to echo?
Answered in the lesson printf and echo: printing text reliably
Questions with model answers
What each question tests, the first step of a good answer and the follow-ups to expect.
-
Mid to senior
A deploy script builds a command in a variable, cmd="rsync -av --exclude='*.log' src/ host:/srv", and runs $cmd. The exclude is ignored and log files are copied. Why, and how do you fix it?
- What it tests
- Knowing that quotes inside a variable's value are not syntax, that expansions are split but not re-parsed, and the safe ways to keep a command: an array or a function.
- First step
- Trace it with bash -x: the trace shows rsync receiving --exclude='*.log' with the quotes inside the word, because quote removal applies only to quotes written in the line, not to quotes that come out of a variable.
- Follow-ups
-
- How would you write it with an array?
- Why is eval a poor fix?
- How do you print the command for a log before running it?
From the lesson How Bash reads a line: tokens and expansions
Model answer, Pro. Model answers open with any pass; prices are in the notice on this page.Opening the model answers with your pass…
Model answers open with any MySmartCoPilot pass.
- Pro pass · 1 week₹79$2.99
- 30 days₹179$5.99
- 1 year₹1,699$45
One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.
Passes can’t be bought right now, so the model answers can’t be opened at the moment. If you have a pass, enter your licence key.
It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).
In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Fresher to mid
A backup loop, for f in $(find . -name '*.pdf'); do cp $f backup/; done, fails with "No such file" for some files and copies others. How do you see exactly what went wrong, and what do you change?
- What it tests
- Using a trace to see the words a command receives, recognising word splitting of command substitution, and replacing the loop with one that keeps names whole.
- First step
- Run the script with bash -x, or put set -x before the loop, and read the traced cp lines: a name with a space shows up as two separate words, which is word splitting of the unquoted $(find …) and of $f.
- Follow-ups
-
- What is the safest loop for names that may contain newlines?
- Why is quoting "$f" alone not enough?
- How do you make the trace easier to read in a long script?
From the lesson How Bash reads a line: tokens and expansions
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Mid to senior
You run ssh web1 "grep 'error' $LOG | wc -l" and get the count of the wrong file. Then a teammate writes the same with single quotes outside and it works. Explain both, and how you pass a local value safely to a remote command.
- What it tests
- Understanding that a command line sent over ssh is parsed twice, by the local and the remote shell, and quoting for two shells with printf %q.
- First step
- Note which shell expands $LOG: in double quotes the local shell expands it before ssh runs, so the remote side gets the local value. In single quotes the text reaches the remote shell unchanged and $LOG is the remote variable.
- Follow-ups
-
- How does printf %q help here?
- What breaks if the value holds a space or a quote?
- When would you send a script on standard input instead?
From the lesson Quoting: single, double, backslash and $'...'
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Fresher to mid
A script prints echo "Price: $5 per item" and shows "Price: per item". Another prints echo 'Hello, $USER' and shows the text $USER. Explain each and fix both.
- What it tests
- Knowing which characters double and single quotes protect, recognising a positional parameter, and choosing the quoting for each part of a message.
- First step
- Read each $ the way the shell does. Inside double quotes $5 is the fifth positional parameter, empty here; inside single quotes $USER is plain text. So the first needs the $ escaped or single-quoted, the second needs double quotes.
- Follow-ups
-
- How would you write a message that holds both a literal $ and a variable?
- Which ShellCheck warnings would have caught these?
- Why does printf make the first one easier?
From the lesson Quoting: single, double, backslash and $'...'
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Mid to senior
You write a wrapper that adds --verbose and then runs the real tool with all the user's arguments. A user passes 'Q3 report.pdf' and the tool says two files are missing. What did the wrapper do wrong, and what is the correct line?
- What it tests
- Knowing the difference between "$@", "$", $@ and $, and passing arguments on without changing their boundaries.
- First step
- Look at how the wrapper passes the arguments: $@ or $* unquoted splits 'Q3 report.pdf' into two words. The correct form is tool --verbose "$@", which passes every argument on as exactly one word.
- Follow-ups
-
- When is "$*" the right choice?
- How would you add an argument at the front or remove the first one?
- How do you test the wrapper?
From the lesson Word splitting and IFS: why "$var" needs quotes
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Mid to senior
A nightly job must delete .log files older than seven days in /var/app/logs and its subfolders. A teammate proposes cd /var/app/logs; rm **/*.log. What risks do you see, and what would you write instead?
- What it tests
- Judging glob behaviour (globstar, no match, dotfiles), the danger of a failed cd, and choosing find for age-based deletion with a dry run first.
- First step
- List what can go wrong before writing anything: if cd fails, rm runs in the wrong folder; without globstar ** is just *; with no match the literal pattern reaches rm; and a glob cannot select by age at all, so find is the right tool.
- Follow-ups
-
- How do you test it safely before the first real run?
- What if a file name begins with a dash?
- How would you log what was deleted?
From the lesson Globbing: wildcards, dotfiles, extglob, globstar
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Senior to staff
Your build script uses shopt -s globstar extglob and GLOBSORT=mtime. It must also run on Macs whose /bin/bash is 3.2.57. What breaks there, and how do you make the script reliable on both?
- What it tests
- Knowing which glob features each Bash version has, detecting the version, and choosing between requiring a newer Bash and writing portable code.
- First step
- Check each feature against its release: extglob exists since 2.02, but globstar needs 4.0 and GLOBSORT 5.3, so on 3.2.57 shopt -s globstar fails and GLOBSORT is silently ignored. Decide whether the script may require a newer Bash.
- Follow-ups
-
- How does the script detect the version?
- What portable command replaces ** here?
- How do you sort by modification time without GLOBSORT?
From the lesson Globbing: wildcards, dotfiles, extglob, globstar
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Fresher to mid
You must create folders q1 to q4 under data/raw and data/clean, and copy settings.yml to a backup before editing it. Show the commands with brace expansion, and say what you check before running them on a server.
- What it tests
- Using nested braces and the {,.bak} idiom correctly, and previewing an expansion with echo before running it.
- First step
- Write the expansions and preview them with echo first: echo mkdir -p data/{raw,clean}/q{1..4} shows the eight paths, and echo cp settings.yml{,.bak} shows the two names, before anything is created or copied.
- Follow-ups
-
- What happens if the script runs under sh?
- How would you do the same when the years come from variables?
- Why does mkdir need -p here?
From the lesson Brace and tilde expansion
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Fresher to mid
A config file holds the line path=~/data, read by a script into a variable and used as cd "$path". The script fails with "No such file or directory", although ~/data exists. Explain and fix it.
- What it tests
- Knowing that tilde expansion happens only on words in the command line, never on values read from files or inside quotes, and replacing the tilde safely.
- First step
- Trace what the variable holds: the tilde came from a file, so it is a plain character, and the shell never expands a tilde inside a variable's value. cd receives the literal ~/data. Replace a leading ~/ with $HOME/ in the value.
- Follow-ups
-
- Why is eval not the answer?
- How do you handle ~otheruser in the file?
- What would you write in the config file instead?
From the lesson Brace and tilde expansion
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Fresher to mid
A report prints name, count and amount with echo and tabs, and the columns drift whenever a name is long. Amounts such as 12.5 print with one decimal. Rewrite the output with printf and explain each part of the format.
- What it tests
- Using printf widths, alignment and precision to build a stable table, and handling long values and money correctly.
- First step
- Decide the columns first: the name left-aligned in a fixed width, the count right-aligned, the amount right-aligned with two decimals. That is printf '%-20s %5d %10.2f\n' "$name" "$count" "$amount", with a header in the same widths.
- Follow-ups
-
- What happens when a name is longer than 20 characters?
- How do you add a total without floating-point errors?
- How would you print the same table as CSV?
From the lesson printf and echo: printing text reliably
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Mid to senior
A logging function is log() { printf "$(date +%T) $1\n"; }. A message such as "disk 95% full" prints garbage, and a message with a backslash prints oddly. What is wrong, and how do you write log() safely?
- What it tests
- Recognising data used as a printf format, rewriting with a fixed format and %s, and keeping the function's behaviour.
- First step
- Point at the format: the message is part of printf's first argument, so its % and backslashes are read as instructions. Move the message into an argument: printf '%s %s\n' "$(date +%T)" "$1".
- Follow-ups
-
- How do you log several arguments at once?
- How can printf produce the time without running date?
- Should the log go to standard output or standard error?
From the lesson printf and echo: printing text reliably
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
All Bash & the POSIX Shell interview questions · The Bash & the POSIX Shell track