LFCA 11 ๐ง The Shell โ What It Is and How It Works
The shell is the program you talk to when you type commands in a terminal. It reads what you type, interprets it, runs programs, and shows you the output. On Linux it’s the primary way to interact with the system โ every command, every script, every automation goes through it. The LFCA exam expects you to know what the shell is, how it processes a command line, the difference between a shell and a terminal, the major shells available, and why the shell remains the most powerful interface on a Linux system decades after graphical desktops arrived.
Key point: A terminal is the window; a shell is the program running inside it. The terminal displays text and passes keystrokes; the shell interprets the commands and runs programs. Most Linux systems use bash as the default shell, but zsh, fish, dash, and others exist. The shell does more than run commands โ it expands variables, globs filenames, pipes output between programs, redirects I/O, and provides the programming language that ties Linux together.
What a shell is
A shell is a command-line interpreter. It reads input from the user (or a script), interprets it, and runs programs on the user’s behalf.
$ echo "hello"
hello
$ ls /etc
adduser.conf apt bash.bashrc ...
$ date
Mon Sep 22 14:30:00 UTC 2025
Each of those lines is a command. The shell reads it, finds the program, runs it with the given arguments, and displays the output.
What the shell does:
- Reads input โ from the terminal or a script
- Parses the command line โ splits it into words, operators, redirections
- Expands โ variables, globs, command substitutions, arithmetic
- Runs programs โ finds them in
$PATHor runs built-ins - Manages I/O โ pipes, redirections, background jobs
- Provides a language โ variables, conditionals, loops, functions
What the shell is not:
- Not the terminal โ that’s the window or console
- Not the kernel โ the shell runs in user space
- Not the same on every system โ multiple shells exist
- Not a single program โ it’s a category of programs
Why it’s called a “shell”: It’s the outer layer around the operating system’s kernel. Users interact with the shell; the shell talks to the kernel through system calls. The kernel does the real work โ the shell wraps it in a friendly interface.
The relationship:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ User โ
โ โ โ
โ โผ โ
โ Terminal (window) โ
โ โ โ
โ โผ โ
โ Shell (bash, zsh, etc.) โ
โ โ โ
โ โผ โ
โ Kernel (system calls) โ
โ โ โ
โ โผ โ
โ Hardware โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Why the shell matters: It’s the interface to everything. Every command, script, cron job, CI/CD pipeline, and container entrypoint runs through a shell. Knowing the shell means knowing how to use Linux โ not just how to click through a desktop.
Why “shell” and not “interpreter”: Both are accurate. The shell interprets commands, but it also does more โ it manages jobs, handles I/O, and provides a scripting language. “Shell” captures the idea that it wraps the kernel. The term is historical, from the earliest Unix systems.
Terminal vs shell
These terms are often used interchangeably, but they’re different things.
A terminal is the interface โ the window or physical device that displays text and captures keystrokes.
A shell is the program running inside the terminal, interpreting commands.
Terminal emulators (modern):
| Terminal | Platform |
|---|---|
| GNOME Terminal | Linux/GNOME |
| Konsole | Linux/KDE |
| xterm | X11 |
| iTerm2 | macOS |
| Windows Terminal | Windows |
| Alacritty | Cross-platform |
| kitty | Cross-platform |
Physical terminals: Before graphical desktops, terminals were real hardware โ a keyboard and screen connected to a Unix machine. The “TTY” (teletype) name survives in /dev/tty and similar paths.
Virtual consoles: On Linux, you can switch between TTY consoles with Ctrl+Alt+F1 through F7. Each runs a shell independent of the graphical session.
Terminal emulators: Programs that simulate a physical terminal inside a graphical environment. When you open a “terminal” on a modern desktop, you’re running a terminal emulator.
The flow:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Terminal emulator โ
โ โ Displays text โ
โ โ Captures keystrokes โ
โ โ Passes bytes to the shell โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ stdin/stdout
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Shell โ
โ โ Reads commands โ
โ โ Interprets, expands, runs โ
โ โ Prints output back โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Why the distinction matters: When you change shells (chsh -s /bin/zsh), you’re changing the program that runs inside the terminal, not the terminal itself. When you open a new terminal, it launches whatever shell is configured as your default.
Why “terminal” persists: The term comes from “computer terminal” โ the device you used to talk to a mainframe. Even though terminals are now software, the name stuck. Some old habits die slowly in computing.
Common shells
Several shells exist, each with different features.
bash โ the Bourne Again Shell:
The most common Linux shell. It’s the default on most distributions and the standard for scripting.
$ echo $SHELL
/bin/bash
| Feature | Available |
|---|---|
| POSIX-compliant | โ (mostly) |
| Scripting | โ |
| Command history | โ |
| Tab completion | โ |
| Job control | โ |
| Arrays | โ |
| Associative arrays | โ (bash 4+) |
| Default on | Most distros |
zsh โ Z Shell:
Popular as an interactive shell, especially on macOS. Extends bash with more features and better defaults.
| Feature | Available |
|---|---|
| POSIX-compliant | โ |
| Scripting | โ |
| Better autocompletion | โ |
| Themes and plugins | โ (oh-my-zsh) |
| Glob qualifiers | โ |
| Default on | macOS (since Catalina) |
fish โ Friendly Interactive Shell:
Designed for interactive use with helpful defaults. Not POSIX-compliant, so scripts may not work.
| Feature | Available |
|---|---|
| POSIX-compliant | โ |
| Scripting | โ (fish syntax) |
| Autosuggestions | โ (built-in) |
| Syntax highlighting | โ |
| Good defaults | โ |
dash โ Debian Almquist Shell:
A minimal POSIX shell. Faster than bash for scripts, used as /bin/sh on Debian/Ubuntu.
| Feature | Available |
|---|---|
| POSIX-compliant | โ |
| Scripting | โ (POSIX only) |
| Interactive features | โ minimal |
| Speed | โ fast |
| Default for | /bin/sh on Debian |
sh โ the POSIX shell:
The standard shell interface. On most systems, /bin/sh is a symlink to dash, bash, or another shell.
$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 ... /bin/sh -> dash
Other shells:
| Shell | Notes |
|---|---|
| csh / tcsh | C-like syntax, older |
| ksh | Korn shell, powerful scripting |
| PowerShell | Microsoft, cross-platform now |
| nushell | Modern, structured data |
| elvish | Modern, expressive |
How to check your shell:
echo $SHELL # login shell
echo $0 # current shell
ps -p $$ # process info
cat /etc/shells # all valid shells
How to change your shell:
chsh -s /bin/zsh
chsh changes the login shell. It takes effect on next login.
Why multiple shells exist: Different needs. Bash for compatibility, zsh for features, fish for friendliness, dash for speed. Interactive use and scripting have different requirements. The variety is a feature โ pick the one that fits.
Why bash is the safe default: It’s on every Linux system, POSIX-compatible enough for portable scripts, and documented everywhere. If you learn one shell, learn bash. Scripts that run on unknown systems should be bash or POSIX
sh.
How the shell processes a command
Every command goes through several steps before it runs.
The pipeline:
- Read โ get the line from the user or file
- Tokenize โ split into words and operators
- Parse โ build a syntax tree (commands, pipes, redirects)
- Expand โ variables, globs, substitutions
- Redirect โ set up input/output
- Execute โ run the program(s)
- Wait โ wait for completion (unless backgrounded)
- Repeat โ read the next line
An example:
$ ls -l *.txt | grep "log" > matches.txt
The shell:
- Tokenizes โ
ls,-l,*.txt,|,grep,"log",>,matches.txt - Parses โ two commands connected by a pipe, second redirected
- Expands โ
*.txtโ actual files likea.txt b.txt c.txt - Sets up I/O โ stdout of
lsโ stdin ofgrep; stdout ofgrepโmatches.txt - Runs โ
lsfirst (writing to the pipe), thengrep - Waits โ for both to finish
Each step matters:
- Tokenizing respects quotes โ
"hello world"is one word - Expansion is why
*.txtbecomes actual filenames - Pipes connect programs without intermediate files
- Redirection writes output where you choose
Where the shell looks for programs: In $PATH, a colon-separated list of directories.
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
The shell checks each directory in order. The first match runs. That’s why /usr/local/bin usually comes before /usr/bin โ local installs override packaged ones.
Built-ins vs external commands:
- Built-ins โ commands the shell itself provides (
cd,echo,pwd,alias) - External commands โ programs in
$PATH(ls,grep,find)
Built-ins run faster and can change shell state (cd affects the current shell). External commands run as separate processes.
How to tell:
$ type cd
cd is a shell builtin
$ type ls
ls is /usr/bin/ls
Why understanding this matters: Shell behavior is the sum of these steps. Variable expansion happening before program execution explains why echo $VAR works. Tokenizing before expansion explains why echo "hello $USER" prints one string but echo hello $USER prints two. The processing model explains most surprises.
Why the shell is not a single program: Different shells implement the process slightly differently. POSIX defines the standard, but bash, zsh, dash, and fish each have extensions. Scripts that use
shshould stick to POSIX; scripts forbashcan use bash features.
Shell features
The shell provides more than command execution.
Variables:
$ name="Alice"
$ echo "Hello, $name"
Hello, Alice
Variables store values. $name expands them. They can be local, exported (visible to child processes), or environment variables.
Environment variables:
$ echo $HOME
/home/alice
$ echo $USER
alice
$ echo $PATH
/usr/local/bin:/usr/bin:/bin
Common environment variables:
| Variable | Contains |
|---|---|
$HOME | User’s home directory |
$USER | Current username |
$PATH | Directories to search |
$PWD | Current working directory |
$SHELL | Login shell |
$LANG | Locale |
$EDITOR | Preferred editor |
Aliases:
$ alias ll='ls -la'
$ ll
Aliases are shortcuts for longer commands. They’re shell features, not programs.
Command history:
$ history
1 ls
2 cd /etc
3 cat hosts
...
$ !3
history lists past commands. !N re-runs the Nth. Up arrow navigates. Ctrl+R searches.
Tab completion:
Typing part of a command and pressing Tab completes it. Filenames, commands, and (with some setup) options.
Glob patterns:
$ ls *.txt # all .txt files
$ ls file?.log # file1.log, fileA.log, ...
$ ls [abc]* # files starting with a, b, or c
The shell expands globs before running the command.
Pipes and redirection:
$ ls | grep "log" # pipe
$ ls > output.txt # redirect stdout
$ ls >> output.txt # append
$ ls 2> errors.txt # redirect stderr
$ ls &> all.txt # stdout and stderr
$ cat < input.txt # redirect stdin
Job control:
$ long_command & # background
$ jobs # list jobs
$ fg # bring to foreground
$ bg # send to background
$ Ctrl+Z # suspend
Command substitution:
$ echo "Today is $(date)"
Today is Mon Sep 22 ...
$ files=$(ls)
$(command) runs the command and substitutes its output.
Arithmetic:
$ echo $((5 + 3))
8
$ count=$((count + 1))
Conditionals and loops: The shell is a programming language.
if [ -f /etc/hosts ]; then
echo "File exists"
fi
for file in *.txt; do
echo "$file"
done
Why the shell is a language: Because it needs to express logic โ conditions, loops, functions. Shell scripting is programming in the shell’s language. That’s why it’s both an interface and a tool.
Why the shell is powerful despite being old: It composes. Small commands, connected by pipes, each doing one thing.
ls | grep | sort | uniq -cuses four programs to produce a report. No other interface composes like that. The shell’s age is its strength โ decades of tools, all designed to work together.
Built-ins and external commands
The shell has two kinds of commands.
Built-ins: Commands implemented inside the shell process.
| Built-in | Purpose |
|---|---|
cd | Change directory |
echo | Print text |
pwd | Show current directory |
alias | Define shortcut |
export | Mark variable for child processes |
source / . | Run a script in the current shell |
set | Shell options |
unset | Remove variable |
exit | Exit the shell |
type | Show command type |
history | Show command history |
jobs | List background jobs |
bg / fg | Job control |
Why some commands are built-in: They must change the shell’s own state. cd changes the current directory โ only the shell can do that. export marks a variable for children. alias defines a shell-level shortcut. External programs can’t change the parent shell’s state.
External commands: Programs in $PATH.
$ which ls cat grep
/usr/bin/ls
/usr/bin/cat
/usr/bin/grep
Each runs as a separate process. When it exits, its state is gone โ it can’t affect the parent shell.
When a name matches both:
$ type echo
echo is a shell builtin
$ which echo
/usr/bin/echo
Both exist. The shell uses the built-in. type -a echo lists all versions.
How the shell decides:
- Check built-ins
- Check aliases
- Check functions
- Check
$PATH
The first match wins. Built-ins take precedence because the shell doesn’t need to spawn a process.
Why this matters for scripting: cd in a script affects the script’s shell, not the caller’s. To change the caller’s directory, you must source the script, not run it. Understanding built-in vs external explains behaviors like this.
Why the distinction persists: The shell’s state is per-process. Only the shell itself can change its own state. External commands run as children and return when done โ they can’t touch the parent. Built-ins exist for the cases where the shell’s state must change.
A full example
A shell session showing the concepts together.
# ============================================
# PART 1: IDENTIFY THE SHELL
# ============================================
echo $SHELL
# /bin/bash
echo $0
# -bash
cat /etc/shells
# /bin/sh
# /bin/bash
# /bin/rbash
# /bin/dash
# /usr/bin/zsh
# ============================================
# PART 2: BUILT-IN VS EXTERNAL
# ============================================
type cd
# cd is a shell builtin
type ls
# ls is /usr/bin/ls
type echo
# echo is a shell builtin
type -a echo
# echo is a shell builtin
# echo is /usr/bin/echo
# ============================================
# PART 3: VARIABLES AND EXPANSION
# ============================================
name="Alice"
echo "Hello, $name"
# Hello, Alice
echo 'Hello, $name'
# Hello, $name
# (single quotes prevent expansion)
# ============================================
# PART 4: PATH AND COMMANDS
# ============================================
echo $PATH
# /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
which grep
# /usr/bin/grep
# ============================================
# PART 5: GLOBS AND PIPES
# ============================================
# Create some test files
cd /tmp
touch file1.txt file2.txt file3.log
ls *.txt
# file1.txt file2.txt
ls | sort
# file1.txt
# file2.txt
# file3.log
ls | grep txt | wc -l
# 2
# ============================================
# PART 6: REDIRECTION
# ============================================
ls /etc > /tmp/listing.txt
wc -l < /tmp/listing.txt
# (number of lines)
ls /nonexistent 2>/tmp/errors.txt
cat /tmp/errors.txt
# ls: cannot access '/nonexistent': No such file or directory
# ============================================
# PART 7: COMMAND SUBSTITUTION
# ============================================
echo "Today is $(date +%A)"
# Today is Monday
files=$(ls /tmp/*.txt)
echo "$files"
# /tmp/file1.txt /tmp/file2.txt
# ============================================
# PART 8: ALIASES
# ============================================
alias ll='ls -la'
alias
# alias ll='ls -la'
# Only in this shell
# To persist, add to ~/.bashrc
# ============================================
# PART 9: HISTORY
# ============================================
history | tail -5
# (last 5 commands)
# ============================================
# PART 10: JOB CONTROL
# ============================================
sleep 10 &
# [1] 12345
jobs
# [1]+ Running sleep 10 &
kill %1
# terminate the job
Every part touches a different shell concept โ identifying the shell, built-ins vs external commands, variables, globs, pipes, redirection, substitution, aliases, history, and job control.
Why this session: It walks through the shell’s features in the order you’d use them. Identify the shell, then use variables, then compose commands with pipes and redirection, then manage jobs. Each concept builds on the previous, and each is something the LFCA exam expects.
Complete Example Session
# ============================================
# PART 1: WHAT SHELL AM I RUNNING?
# ============================================
echo $SHELL
# [ /bin/bash ]
echo $0
# [ bash ]
ps -p $$
# [ PID TTY TIME CMD ]
# [ 12345 pts/0 00:00:00 bash ]
cat /etc/shells
# [ /bin/sh ]
# [ /bin/bash ]
# [ /bin/rbash ]
# [ /bin/dash ]
# [ /usr/bin/zsh ]
# ============================================
# PART 2: TYPE CHECKING
# ============================================
type pwd
# [ pwd is a shell builtin ]
type cat
# [ cat is /usr/bin/cat ]
type -a test
# [ test is a shell builtin ]
# [ test is /usr/bin/test ]
# ============================================
# PART 3: VARIABLES
# ============================================
greeting="Hello, World"
echo "$greeting"
# [ Hello, World ]
echo '$greeting'
# [ $greeting ]
export EDITOR=vim
echo $EDITOR
# [ vim ]
# ============================================
# PART 4: PATH
# ============================================
echo $PATH | tr ':' '\n'
# [ /usr/local/sbin ]
# [ /usr/local/bin ]
# [ /usr/sbin ]
# [ /usr/bin ]
# [ /sbin ]
# [ /bin ]
which python3
# [ /usr/bin/python3 ]
# ============================================
# PART 5: GLOBS
# ============================================
cd /tmp
touch a.txt b.txt c.log d.txt
echo *.txt
# [ a.txt b.txt d.txt ]
echo ?.txt
# [ a.txt b.txt d.txt ]
echo [ab].txt
# [ a.txt b.txt ]
# ============================================
# PART 6: PIPES
# ============================================
ls /etc | wc -l
# [ 220 ]
cat /etc/passwd | grep bash | wc -l
# [ (number of bash users) ]
ps aux | grep ssh | head -3
# ============================================
# PART 7: REDIRECTION
# ============================================
date > /tmp/now.txt
cat /tmp/now.txt
date >> /tmp/now.txt
wc -l < /tmp/now.txt
# [ 2 ]
ls /nonexistent 2> /tmp/err.txt
cat /tmp/err.txt
# ============================================
# PART 8: COMMAND SUBSTITUTION
# ============================================
uptime_seconds=$(cut -d. -f1 /proc/uptime)
echo "System has been up for $uptime_seconds seconds"
kernel=$(uname -r)
echo "Kernel: $kernel"
# ============================================
# PART 9: ALIASES AND FUNCTIONS
# ============================================
alias ll='ls -la'
alias grep='grep --color=auto'
myfunc() {
echo "Hello from $1"
}
myfunc "test"
# [ Hello from test ]
# ============================================
# PART 10: JOB CONTROL
# ============================================
sleep 30 &
# [ [1] 54321 ]
jobs
# [ [1]+ Running sleep 30 & ]
fg %1
# (brings sleep to foreground)
# Ctrl+Z suspends
# bg sends back to background
kill %1
# ============================================
# PART 11: BUILT-IN COMMANDS
# ============================================
cd /etc
pwd
# [ /etc ]
cd -
# [ /tmp ]
export MYVAR="test"
env | grep MYVAR
unset MYVAR
echo "$MYVAR"
# (empty)
# ============================================
# PART 12: SCRIPTING PREVIEW
# ============================================
if [ -f /etc/hosts ]; then
echo "Hosts file exists"
fi
for f in /tmp/*.txt; do
echo "File: $f"
done
count=0
while [ $count -lt 3 ]; do
echo "Count: $count"
count=$((count + 1))
done
Each section exercises a shell concept. Together they form a tour of what the shell does.
Quick Reference
Shell vs Terminal
| Aspect | Terminal | Shell |
|---|---|---|
| What it is | Window or device | Program |
| Role | Display + input | Interpret + execute |
| Example | GNOME Terminal | bash |
| Changes with | chsh | Default config |
Common Shells
| Shell | Path | Notes |
|---|---|---|
| bash | /bin/bash | Default on most Linux |
| zsh | /usr/bin/zsh | macOS default |
| fish | /usr/bin/fish | Friendly, not POSIX |
| dash | /bin/dash | Fast, POSIX, Debian |
| sh | /bin/sh | POSIX, symlink |
| ksh | /bin/ksh | Korn shell |
| csh/tcsh | /bin/csh | C-like |
Identifying the Shell
| Command | Shows |
|---|---|
echo $SHELL | Login shell |
echo $0 | Current shell |
ps -p $$ | Shell process |
cat /etc/shells | Valid shells |
chsh -s PATH | Change login shell |
Command Processing Steps
| Step | What happens |
|---|---|
| 1 | Read input |
| 2 | Tokenize |
| 3 | Parse |
| 4 | Expand (vars, globs, subs) |
| 5 | Set up redirection |
| 6 | Execute |
| 7 | Wait |
| 8 | Repeat |
Built-in vs External
| Aspect | Built-in | External |
|---|---|---|
| Runs in | Shell process | Separate process |
| Can change shell state | โ | โ |
| Examples | cd, echo, pwd | ls, grep, find |
| Speed | Fast | Slower (new process) |
| Check with | type | which |
Common Built-ins
| Built-in | Purpose |
|---|---|
cd | Change directory |
pwd | Print working directory |
echo | Print text |
export | Mark variable for export |
alias | Define shortcut |
source / . | Run script in current shell |
set | Shell options |
unset | Remove variable |
exit | Exit shell |
type | Show command type |
history | Command history |
jobs | Background jobs |
bg / fg | Job control |
Environment Variables
| Variable | Contains |
|---|---|
$HOME | Home directory |
$USER | Username |
$PATH | Search path |
$PWD | Current directory |
$SHELL | Login shell |
$LANG | Locale |
$EDITOR | Preferred editor |
$PS1 | Prompt |
Shell Features
| Feature | Example |
|---|---|
| Variables | name="Alice" |
| Expansion | $name, ${name} |
| Globs | *.txt, file?.log |
| Pipes | ls | grep x |
| Redirection | cmd > file |
| Command substitution | $(date) |
| Arithmetic | $((5 + 3)) |
| Aliases | alias ll='ls -la' |
| Functions | f() { ... } |
| Conditionals | if [ ... ]; then |
| Loops | for x in ...; do |
Redirection Operators
| Operator | Effect |
|---|---|
> | Redirect stdout (overwrite) |
>> | Redirect stdout (append) |
2> | Redirect stderr |
&> | Both stdout and stderr |
< | Redirect stdin |
| | Pipe stdout to next |
tee | Write to file and screen |
Job Control
| Command | Action |
|---|---|
cmd & | Run in background |
jobs | List jobs |
fg %n | Foreground job |
bg %n | Background job |
Ctrl+Z | Suspend current |
Ctrl+C | Interrupt current |
kill %n | Kill job |
Path-Related
| Command | Purpose |
|---|---|
pwd | Current directory |
cd DIR | Change directory |
cd ~ | Home |
cd - | Previous |
which CMD | Location in PATH |
type CMD | Type of command |
whereis CMD | Binary + docs |
Globs
| Pattern | Matches |
|---|---|
* | Any characters |
? | One character |
[abc] | a, b, or c |
[a-z] | Range |
[!abc] | Not a, b, or c |
~ | Home directory |
{a,b} | a or b (brace expansion) |
Special Characters
| Character | Meaning |
|---|---|
\ | Escape next character |
'...' | Literal (no expansion) |
"..." | Mostly literal ($, \, backtick still work) |
`...` | Command substitution (legacy) |
$(...) | Command substitution |
; | Command separator |
&& | Run next if previous succeeds |
|| | Run next if previous fails |
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Success |
| Non-zero | Failure |
$? | Last exit code |
$! | PID of last background job |
Files Configuring the Shell
| File | Purpose |
|---|---|
~/.bashrc | bash interactive config |
~/.bash_profile | bash login config |
~/.zshrc | zsh config |
/etc/bash.bashrc | system bash config |
/etc/profile | system login config |
Switching Shells
| Action | Command |
|---|---|
| Run a shell | bash, zsh, fish |
| Change default | chsh -s /bin/zsh |
| Run script in specific shell | zsh script.sh |
| Force POSIX behavior | sh script.sh |
Best Practices
โ Do This:
# Check your shell before assuming
echo $SHELL # โ
# Use type to see if a command is built-in
type cd # โ
# Quote variables in scripts
echo "$name" # โ
# Use single quotes for literals
echo '$PATH' # โ
# Prefer $(...) over backticks
echo "$(date)" # โ
# Use built-ins when state matters
cd /etc # โ
# Use external commands for processing
grep "pattern" file.txt # โ
# Redirect stderr when ignoring errors
command 2>/dev/null # โ
# Check exit codes in scripts
if command; then ... fi # โ
# Read your rc files
cat ~/.bashrc # โ
โ Don’t Do This:
# Don't assume sh is bash
sh script.sh # POSIX only # โ ๏ธ
# Don't use unquoted variables with spaces
cp $file /dest # breaks on spaces # โ
# Don't rely on alias in scripts
alias ll='ls -la' # won't apply in scripts # โ ๏ธ
# Don't use cd in a script expecting to affect caller
# Scripts run in subshells # โ
# Don't ignore exit codes
rm file # if this fails, continue anyway? # โ ๏ธ
# Don't use backticks in new scripts
echo `date` # use $(date) # โ ๏ธ
# Don't overwrite files with > accidentally
echo "x" > important.txt # overwrites! # โ
# Don't use rm without thinking
rm -rf /tmp/* # what if /tmp/* matches more? # โ
# Don't run untrusted scripts as root
sudo bash script.sh # โ ๏ธ
Common Pitfalls
| Pitfall | Problem | Solution |
|---|---|---|
| Assuming sh = bash | Script fails | Use #!/bin/bash or POSIX |
Unquoted $var | Word splitting | Always quote |
| Single vs double quotes | No expansion | Know the difference |
> overwrites | Data loss | Use >> to append |
| Alias in script | Not applied | Use functions or full commands |
cd in script | Affects script only | source to affect caller |
| Ignoring exit codes | Silent failures | Check $? |
| Wrong shell interpreter | Syntax errors | Check shebang |
| Globs expanding unexpectedly | Wrong files | Quote patterns |
| Path order matters | Wrong binary runs | Check $PATH order |
Real-World Examples
1. Check current shell
echo $SHELL
2. List available shells
cat /etc/shells
3. Change login shell
chsh -s /bin/zsh
4. Show PATH
echo $PATH
5. Find a command
which ls
6. Check if built-in
type cd
7. Show all matches
type -a echo
8. Set a variable
name="Alice"
9. Export for child processes
export EDITOR=vim
10. Use command substitution
echo "Kernel: $(uname -r)"
11. Pipe commands
ls | grep .txt
12. Redirect to file
ls /etc > listing.txt
13. Append to file
date >> log.txt
14. Redirect stderr
command 2> errors.txt
15. Discard output
command > /dev/null 2>&1
16. Background a job
long_task &
17. Check jobs
jobs
18. Create an alias
alias ll='ls -la'
19. Check exit code
echo $?
20. Read rc file
cat ~/.bashrc
Visual: User to Kernel
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ User โ
โ โ types a command โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ keystrokes
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Terminal โ
โ โ displays characters โ
โ โ captures input โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ bytes
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Shell โ
โ โ parses the line โ
โ โ expands variables and globs โ
โ โ sets up pipes and redirection โ
โ โ runs the program โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ system calls
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Kernel โ
โ โ executes the process โ
โ โ manages files, processes, hardware โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ output
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Terminal โ User โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: Command Processing
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ $ ls -l *.txt | grep log > matches.txt โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 1. Tokenize โ
โ ls -l *.txt | grep log > matches.txtโ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 2. Parse โ
โ cmd1: ls -l *.txt โ
โ cmd2: grep log โ
โ pipe: cmd1 | cmd2 โ
โ redirect: cmd2 > matches.txt โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 3. Expand โ
โ *.txt โ a.txt b.txt c.txt โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 4. Set up I/O โ
โ ls stdout โ pipe โ grep stdin โ
โ grep stdout โ matches.txt โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 5. Execute โ
โ Run ls โ write to pipe โ
โ Run grep โ read from pipe โ write file โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: Built-in vs External
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Built-in (cd, echo, pwd) โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Shell process โ โ
โ โ โ parses command โ โ
โ โ โ runs built-in directly โ โ
โ โ โ can change shell state โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ External (ls, grep, find) โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Shell process โ โ
โ โ โ parses command โ โ
โ โ โ forks a child process โ โ
โ โโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Child process โ โ
โ โ โ executes ls or grep โ โ
โ โ โ can't change parent shell state โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: Common Shells
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ bash โโโโโโ default on most Linux โ
โ โ POSIX, arrays, functions, history โ
โ โ
โ zsh โโโโโโโ macOS default โ
โ โ bash superset, better completion โ
โ โ
โ fish โโโโโโ friendly, not POSIX โ
โ โ autosuggestions, highlighting โ
โ โ
โ dash โโโโโโ fast, minimal POSIX โ
โ โ /bin/sh on Debian/Ubuntu โ
โ โ
โ sh โโโโโโโโ POSIX standard โ
โ โ symlink to bash, dash, or other โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: Pipes and Redirection
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ $ ls | grep log โ
โ โ
โ ls โโโโ stdout โโโโโ โ
โ โ โ
โ โผ โ
โ [pipe] โ
โ โ โ
โ โผ โ
โ grep โโโโ stdin โโโโ โ
โ โโโโโ stdout โโโโโบ terminal โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ $ ls > files.txt โ
โ โ
โ ls โโโโ stdout โโโโโบ files.txt โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ $ cat < input.txt โ
โ โ
โ input.txt โโโโ stdin โโโโโบ cat โ
โ โโโโ stdout โโโบ termโ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: Variable Expansion
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ $ name="Alice" โ
โ $ echo "Hello, $name" โ
โ โ
โ Before expansion: โ
โ echo "Hello, $name" โ
โ โ
โ After expansion: โ
โ echo "Hello, Alice" โ
โ โ
โ Command runs with expanded argument โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Double quotes: expand $, ``, \ โ
โ Single quotes: literal โ
โ โ
โ echo "$name" โ Hello, Alice โ
โ echo '$name' โ Hello, $name โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: PATH Search
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ $ which ls โ
โ โ
โ PATH=/usr/local/sbin:/usr/local/bin: โ
โ /usr/sbin:/usr/bin:/sbin:/bin โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Search order: โ
โ โ
โ 1. /usr/local/sbin/ls โ not found โ
โ 2. /usr/local/bin/ls โ not found โ
โ 3. /usr/sbin/ls โ not found โ
โ 4. /usr/bin/ls โ FOUND โ
โ
โ โ
โ Run /usr/bin/ls โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: Job Control
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ $ sleep 60 & โ
โ [1] 12345 โ
โ โ
โ Background job runs, prompt returns โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ $ jobs โ
โ [1]+ Running sleep 60 & โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ $ fg %1 โ
โ sleep 60 โ
โ (Ctrl+Z) โ
โ [1]+ Stopped sleep 60 โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ $ bg %1 โ
โ [1]+ sleep 60 & โ
โ (running in background again) โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: Shell Configuration Files
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ System-wide: โ
โ โ /etc/profile โ
โ โ /etc/bash.bashrc โ
โ โ /etc/profile.d/*.sh โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ User-specific (bash): โ
โ โ ~/.bash_profile (login shells) โ
โ โ ~/.bashrc (interactive) โ
โ โ ~/.bash_logout (on logout) โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ User-specific (zsh): โ
โ โ ~/.zshrc โ
โ โ ~/.zprofile โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: Decision Flow
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Need to change something in the shell? โ
โ โ โ
โ โโโ Use a built-in โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Need to process files or data? โ
โ โ โ
โ โโโ Use external commands โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Need to connect commands? โ
โ โ โ
โ โโโ Pipe or redirect โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Need it to persist across sessions? โ
โ โ โ
โ โโโ Add to ~/.bashrc or ~/.zshrc โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Need it in scripts? โ
โ โ โ
โ โโโ Use functions, not aliases โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
| Concept | Meaning |
|---|---|
| Shell | Program that interprets commands |
| Terminal | Window or device that runs the shell |
| bash | Default shell on most Linux |
| zsh | Feature-rich, macOS default |
| fish | Friendly, not POSIX |
| dash | Fast, minimal POSIX |
| Built-in | Command in the shell process |
| External | Program in $PATH |
| Variable | Named value |
| Expansion | Replace $var with value |
| Glob | Pattern like *.txt |
| Pipe | Connect programs |
| Redirection | Route I/O to files |
| Job control | Background and foreground |
Key takeaways:
- The shell interprets commands; the terminal is the window it runs in
- bash is the standard Linux shell; zsh, fish, and dash are alternatives
- The shell processes a command line in stages: tokenize, parse, expand, execute
- Built-ins run in the shell process and can change its state; external commands run as separate processes
- Variables store values;
$nameexpands them - Globs โ
*.txt,file?โ expand to matching filenames - Pipes โ
|โ connect the output of one command to the input of another - Redirection โ
>,>>,<,2>โ routes input and output - Command substitution โ
$(cmd)โ inserts a command’s output - Job control โ
&,jobs,fg,bg,Ctrl+Zโ manages background processes - Aliases are shortcuts; functions are scripts inside the shell
- The shell is a programming language โ variables, conditionals, loops
~/.bashrcand~/.zshrcconfigure the shell per user/etc/shellslists valid shells;chsh -schanges the login shell
Remember: The shell is the interface to Linux โ the program that reads your commands, interprets them, and runs them. It’s not the terminal, which is just the window. It provides variables, globs, pipes, redirection, and job control โ features that make command-line work powerful. bash is the standard, but zsh, fish, and dash each have strengths. Understanding what the shell does โ and how it processes a command โ is the foundation for everything else in Linux. Every script, every automation, every CI/CD pipeline runs through a shell.
Stop using slow, ad-bloated tool sites! ๐คฎ
๐ Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
โ
Finance (Mortgage, Interest, Inflation)
โ
Tech (Base64, JSON, Dev Suite, IP)
โ
Health (BMI, BMR, TDEE)
โ
Productivity (Timer, Workspace, QR)
โก๏ธ Fast & Private
๐ No data leaves your device
๐ 100% Free
๐ Use it now: https://tools.kandz.me
๐ Bookmark itโyouโll need it later!