Shell and Bash Basics

Introduction

The shell is your command-line interpreter—usually bash on Ubuntu. It parses what you type, runs programs, connects them with pipes, and holds environment variables like PATH. This chapter builds habits you use on every server: options, redirection, chaining, and shell config files.

Prerequisites

Shell, Terminal, and Kernel

LayerRole
TerminalWindow that displays text (GNOME Terminal, Windows Terminal, iTerm)
ShellProgram that reads commands (bash, zsh)
KernelRuns processes, manages files and hardware

You type into the terminal; bash launches ls, java, node, etc.

Check your shell:

bash
# Print shell name
echo $SHELL
 
# Bash version
bash --version

This course assumes bash. macOS default zsh is similar for basics; server Ubuntu uses bash.

Command Structure

text
command   -options   arguments

Example:

bash
# ls = command, -la = options, /var/log = argument
ls -la /var/log
  • Options often start with - (-l) or -- (--help).
  • Order matters for some commands; when unsure, read --help.
bash
# Built-in help
ls --help
man ls

Environment Variables

bash
# Show one variable
echo $HOME
echo $PATH
 
# List environment
env | head
 
# Set for current session
export MY_APP_ENV=dev
echo $MY_APP_ENV

PATH is a colon-separated list of directories bash searches for executables:

bash
# See search path
echo $PATH

After installing JDK or Node on Linux, installers often append to PATH or you add lines to ~/.bashrc—see Java on Linux and Node on Linux.

Persist for your user:

bash
# Append to ~/.bashrc (example)
echo 'export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64' >> ~/.bashrc
echo 'export PATH="$JAVA_HOME/bin:$PATH"' >> ~/.bashrc
 
# Reload
source ~/.bashrc

Shell Startup Files (Simplified)

FileWhen loaded
~/.profileLogin shells
~/.bashrcInteractive non-login bash (common on Ubuntu)

Put personal alias and export in ~/.bashrc. System-wide defaults live under /etc/profile.d/.

Aliases and History

bash
# Short alias
alias ll='ls -la'
ll ~
 
# List recent commands
history | tail
 
# Re-run command 42 from history
!42

Standard Streams and Redirection

StreamFDDefault
stdin0Keyboard
stdout1Terminal
stderr2Terminal
bash
# Redirect stdout to file (overwrite)
echo "hello" > out.txt
 
# Append
echo "world" >> out.txt
 
# Redirect stderr
ls /nope 2> errors.txt
 
# Combine stdout and stderr
somecommand > all.log 2>&1

Read from file:

bash
# Count lines in file as stdin
wc -l < out.txt

Pipes and tee

Pipe connects stdout of one command to stdin of the next:

bash
# Count lines in sorted unique words
cat /etc/passwd | cut -d: -f1 | sort | uniq | wc -l

tee writes to file and still passes data through:

bash
# Save and display
ls -la | tee listing.txt

Command Chaining

bash
# Run second only if first succeeds
mkdir ~/demo && touch ~/demo/ok.txt
 
# Run second only if first fails
test -f /missing || echo "file missing"
 
# Run both regardless
cd ~; pwd

Use && in deploy scripts to stop on failure (pairs with set -e in scripts later).

Job Control (Brief)

bash
# Long running (example)
sleep 100
 
# Ctrl+C stops foreground job
 
# Run in background
sleep 100 &
jobs
 
# Bring to foreground
fg %1

Ctrl+Z suspends; bg resumes in background—handy for long tasks over SSH.

Useful Shortcuts

ShortcutEffect
Ctrl+CInterrupt running command
Ctrl+L or clearClear screen
Ctrl+RReverse search history
TabComplete command/path

Mini Example: Inspect Java on PATH

bash
# Which java binary runs
which java
 
# Version if installed
java -version 2>&1 | head -n 3
 
# Show PATH entries one per line
echo "$PATH" | tr ':' '\n' | grep -i java

FAQ

bash vs sh?

sh may point to dash on Ubuntu—scripts for portability use #!/bin/bash when bash features are needed.

Why is my export gone after reboot?

You only typed export in the session—add it to ~/.bashrc or /etc/environment.

Pipe stderr?

command 2>&1 | grep error merges stderr into the pipe.

What comes next?

Viewing and editing text.