Unix - UNIX shell

What is a shell?

A shell is both:

  • a command-line interface (you type commands, it runs them), and

  • a scripting language (you write programs in it to automate work).

It sits between you and the kernel. You type a command; the shell parses it, performs expansions and redirections, sets up pipelines, and then either runs a builtin (inside the shell process) or launches an external program via the kernel.

Popular shells (quick map)

  • sh: Original Bourne shell; portable scripts.

  • bash: Bourne Again SHell (very common on Linux); arrays, [[ ]], brace expansion, history, job control.

  • ksh: Korn shell; strong in scripting, arithmetic.

  • csh/tcsh: C-like syntax; interactive niceties, less favored for scripting.

  • zsh: Powerful completion/prompt; great interactive experience.

Check your shell: echo "$SHELL" or for a user: getent passwd "$USER".

What happens when you run a command

Example:

grep -i "error" /var/log/syslog | awk '{print $1,$2}' > errors.txt

Under the hood:

  1. Lexing & parsing — the shell splits the line into commands and operators (|, >).

  2. Expansions — quotes handled; variables/$(...)/$((...))/globs resolved.

  3. Redirections & FDs> redirects STDOUT (file descriptor 1) to errors.txt.

  4. Pipelines — shell creates a pipe; connects grep’s STDOUT to awk’s STDIN.

  5. Execution — for each external command, shell does fork() then execve(); the kernel loads the program.

  6. Exit status$? holds the last program’s exit code (0 = success).

Builtins vs external programs

  • Builtins run inside the shell: cd, echo, readonly, export, alias, type, jobs, ulimit.

  • External tools are separate executables found via $PATH: ls, cp, grep, awk, sed, tar, etc.

See which you’re calling: type cd, type echo, type grep.

Redirection & pipelines (FDs 0/1/2)

  • cmd > out.txt write STDOUT to file

  • cmd >> out.txt append

  • cmd < in.txt read STDIN from file

  • cmd 2> err.txt write STDERR to file

  • cmd > all.txt 2>&1 merge STDERR into STDOUT

  • a | b | c connect outputs to inputs through pipes

  • tee to both screen and file: cmd | tee log.txt

Variables, quoting, and expansions

name="Ada Lovelace"     # no spaces around =
echo "$name"            # double quotes preserve spaces, expand variables
echo 'literal $name'    # single quotes prevent expansion
echo "Today is $(date)" # command substitution
echo $((3 * (4 + 5)))   # arithmetic
printf '%s\n' *.txt     # pathname expansion (globbing)

Export to children: export PATH="$HOME/bin:$PATH".

Shell scripting essentials

  1. Shebang: first line picks the interpreter
    #!/usr/bin/env bash

  2. Make it executable: chmod +x script.sh

  3. Run: ./script.sh (or bash script.sh)

A robust template often starts with:

set -euo pipefail
IFS=$'\n\t'
  • -e exit on unhandled error

  • -u error on unset vars

  • -o pipefail propagate pipeline failures

  • IFS tuned for safe word-splitting

A complete, practical example script

I’ve prepared a thoroughly commented script that demonstrates:

  • options with getopts

  • variables, arrays, functions

  • error handling with trap

  • pipelines, redirection, tee

  • here-documents

  • safe file handling with find -print0 and mapfile

Download the example script

You can run it like:

./shell_example.sh -s /var/log -d ~/backups -p "*.log"
./shell_example.sh -s ./data -d ./out -n   # dry run

Job control (interactive superpower)

  • Run in background: long_task &

  • Suspend: Ctrl+Z

  • Bring to foreground/background: fg, bg

  • List: jobs

  • Keep running after logout: nohup cmd & or disown

Login vs interactive vs non-interactive shells (Bash example)

  • Login shells read /etc/profile then ~/.bash_profile (or ~/.profile).

  • Interactive non-login shells (typical new terminal) read ~/.bashrc.

  • Non-interactive shells (scripts) read BASH_ENV if set.

A common setup is: in ~/.bash_profile, source ~/.bashrc so both paths share aliases, prompt, etc.

Common pitfalls (and fixes)

  • Spaces in assignments: x=5 ✅ vs x = 5

  • Quoting: quote "$var" unless you intentionally want word-splitting/globbing.

  • Redirection with sudo: sudo cmd > file fails if you can’t write file. Use sudo sh -c 'cmd > file' or cmd | sudo tee file.

  • [ vs [[ (Bash): prefer [[ ... ]] for safer conditionals.

  • Globs on empty matches: consider shopt -s nullglob when appropriate.

At-a-glance cheat sheet

  • Find programs: which, type, command -v

  • Measure time: time cmd

  • Functions:

    myfunc(){ local x=$1; echo "$x"; }
    
  • Conditionals:

    if [[ -f file && -r file ]]; then ...; fi
    
  • Loops:

    for f in *.txt; do echo "$f"; done
    while read -r line; do ...; done < input.txt