The commands you reach for every day — and the shell patterns you look up every time. This covers navigation, file operations, text processing, scripting constructs, and process control.
Quick reference
The 24 commands that cover 90% of daily terminal work.
| Command | What it does |
|---|---|
pwd |
Print current directory |
ls -la |
List files (long format, hidden) |
cd ~ |
Go to home directory |
mkdir -p a/b/c |
Create nested directories |
cp -r src/ dst/ |
Copy directory recursively |
mv old new |
Move or rename |
rm -rf dir/ |
Remove directory (irreversible) |
cat file.txt |
Print file contents |
head -n 20 file |
First 20 lines |
tail -f log.txt |
Follow live log |
grep -r "text" . |
Search in files recursively |
find . -name "*.js" |
Find files by name |
chmod +x script.sh |
Make executable |
echo $VAR |
Print variable |
export VAR=value |
Set environment variable |
ps aux |
List all processes |
kill -9 PID |
Force kill process |
wc -l file.txt |
Count lines |
sort file.txt |
Sort lines |
uniq -c |
Count unique lines |
cut -d',' -f1 |
Extract first CSV column |
sed 's/old/new/g' |
Replace text inline |
awk '{print $2}' |
Print second field |
curl -s URL |
Fetch URL silently |
Navigation and files
# Navigation
pwd # current directory
cd /etc # absolute path
cd .. # parent directory
cd - # previous directory
ls -la # all files, long format
ls -lh # human-readable sizes
# Create and remove
mkdir mydir
mkdir -p a/b/c # create all parent dirs
touch file.txt # create empty file
rmdir emptydir # remove empty dir only
rm -rf dir/ # remove dir recursively (no undo!)
# Copy and move
cp file.txt backup.txt
cp -r src/ dst/ # copy directory
mv old.txt new.txt # rename
mv file.txt /tmp/ # move to /tmp/
# View files
cat file.txt # print whole file
less file.txt # page through (q to quit)
head -n 20 file.txt # first 20 lines
tail -n 20 file.txt # last 20 lines
tail -f /var/log/app.log # follow live (Ctrl+C to stop)
# File info
wc -l file.txt # line count
wc -w file.txt # word count
du -sh dir/ # directory size
df -h # disk usage
stat file.txt # metadata: size, mtime, inode
Text processing
# grep — search
grep "error" app.log # lines matching pattern
grep -i "error" app.log # case insensitive
grep -r "TODO" src/ # recursive in directory
grep -n "error" app.log # show line numbers
grep -v "debug" app.log # invert: lines NOT matching
grep -E "err|warn" app.log # extended regex (OR)
grep -c "error" app.log # count matching lines
# sed — stream editor
sed 's/old/new/' file.txt # replace first occurrence per line
sed 's/old/new/g' file.txt # replace all occurrences
sed -i 's/foo/bar/g' file.txt # edit file in place
sed -n '5,10p' file.txt # print lines 5–10
sed '/pattern/d' file.txt # delete matching lines
# awk — field processing
awk '{print $1}' file.txt # first field (default sep: whitespace)
awk -F',' '{print $2}' data.csv # second CSV column
awk '{sum += $1} END {print sum}' # sum first column
awk 'NR==5' file.txt # print line 5
awk 'length($0) > 80' file.txt # lines longer than 80 chars
# cut, sort, uniq
cut -d',' -f1,3 data.csv # extract columns 1 and 3
sort file.txt # sort alphabetically
sort -n numbers.txt # sort numerically
sort -rn numbers.txt # sort numerically, descending
sort -u file.txt # sort and deduplicate
uniq file.txt # remove adjacent duplicates (needs sort first)
uniq -c file.txt # prefix with count
sort file.txt | uniq -c | sort -rn # frequency table
Redirection and pipes
# Output redirection
command > out.txt # overwrite
command >> out.txt # append
command 2> err.txt # stderr only
command > out.txt 2>&1 # stdout + stderr to same file
command > /dev/null 2>&1 # discard all output
# Pipes — chain commands
cat file.txt | grep "error" | sort | uniq -c
ls -la | grep "\.sh$"
ps aux | grep nginx | grep -v grep
# tee — write to file AND stdout
command | tee output.txt
command | tee -a output.txt # append
# Here-string and heredoc
grep "word" <<< "word in a string"
cat <<EOF > config.txt
line one
line two
EOF
# Process substitution
diff <(sort file1.txt) <(sort file2.txt)
Variables and arithmetic
# Variables — no spaces around =
name="Alice"
echo $name # prints Alice
echo "${name}s" # Alices — brace prevents ambiguity
# Special variables
$0 # script name
$1 $2 ... # positional args
$# # number of args
$@ # all args as separate words
$* # all args as single word
$? # exit code of last command
$$ # current PID
$! # PID of last background process
# Command substitution
today=$(date +%Y-%m-%d)
files=$(ls *.txt)
count=$(wc -l < file.txt)
# Arithmetic (integers only)
echo $((3 + 4)) # 7
echo $((10 % 3)) # 1
n=5; echo $((n * 2)) # 10
x=$((x + 1)) # increment
# String operations
str="hello world"
echo ${#str} # length: 11
echo ${str:0:5} # substring: hello
echo ${str/world/bash} # replace: hello bash
echo ${str^^} # uppercase: HELLO WORLD
echo ${str,,} # lowercase
# Default values
echo ${VAR:-default} # default if VAR unset or empty
echo ${VAR:=default} # assign default if unset
echo ${VAR:?error message} # exit with error if unset
Conditionals
# if / elif / else
if [ "$x" -gt 10 ]; then
echo "big"
elif [ "$x" -eq 10 ]; then
echo "ten"
else
echo "small"
fi
# Common test operators
# Numbers: -eq -ne -lt -le -gt -ge
# Strings: = != -z (empty) -n (not empty)
# Files: -f (file) -d (dir) -e (exists) -r -w -x
# [[ double brackets — bash only, more features ]]
if [[ "$str" == *"hello"* ]]; then echo "contains hello"; fi
if [[ "$str" =~ ^[0-9]+$ ]]; then echo "all digits"; fi
# case
case "$day" in
Mon|Tue|Wed|Thu|Fri) echo "Weekday" ;;
Sat|Sun) echo "Weekend" ;;
*) echo "Unknown" ;;
esac
# Inline conditionals
command && echo "success" || echo "failed"
[ -f file.txt ] && cat file.txt
Loops
# for — range
for i in {1..5}; do
echo "Item $i"
done
# for — array
fruits=("apple" "banana" "cherry")
for fruit in "${fruits[@]}"; do
echo "$fruit"
done
# for — C style
for ((i=0; i<10; i++)); do
echo $i
done
# for — files
for f in *.txt; do
echo "Processing $f"
done
# while
count=0
while [ $count -lt 5 ]; do
echo $count
((count++))
done
# while — read file line by line
while IFS= read -r line; do
echo ">> $line"
done < file.txt
# until — runs while condition is FALSE
until ping -c1 google.com &>/dev/null; do
echo "Waiting for network..."
sleep 1
done
# Loop control
break # exit loop
continue # skip to next iteration
Functions
# Define
greet() {
local name="$1" # local variables prevent leaks
echo "Hello, $name!"
return 0 # return 0 = success
}
# Call
greet "Alice"
# Capture return value (use stdout, not return code)
get_date() {
echo "$(date +%Y-%m-%d)"
}
today=$(get_date)
# Function with default args
backup() {
local src="${1:?Source required}"
local dst="${2:-/tmp/backup}"
cp -r "$src" "$dst"
}
Process management
# List processes
ps aux # all processes
ps aux | grep nginx
top # interactive process viewer
htop # better top (may need install)
# Background / foreground
command & # run in background
jobs # list background jobs
fg %1 # bring job 1 to foreground
bg %1 # resume job 1 in background
nohup command & # keep running after logout
disown %1 # detach from shell
# Kill
kill PID # graceful (SIGTERM)
kill -9 PID # force kill (SIGKILL)
killall nginx # kill by name
pkill -f "pattern" # kill by command pattern
# Wait and timing
wait # wait for all background jobs
sleep 5 # pause 5 seconds
time command # measure execution time
Permissions
# chmod — change mode
chmod +x script.sh # add execute for all
chmod 755 script.sh # rwxr-xr-x
chmod 644 file.txt # rw-r--r--
chmod -R 755 dir/ # recursive
# Permission bits: rwxrwxrwx → owner | group | others
# 4=read 2=write 1=execute → 7=rwx 6=rw- 5=r-x 4=r-- 0=---
# chown — change owner
chown user file.txt
chown user:group file.txt
chown -R user:group dir/
# View permissions
ls -la
stat file.txt
Networking
# curl
curl https://api.example.com # GET
curl -s URL # silent (no progress)
curl -o out.html URL # save to file
curl -L URL # follow redirects
curl -I URL # headers only
curl -X POST -H "Content-Type: application/json" \
-d '{"key":"val"}' URL # POST JSON
curl -u user:pass URL # basic auth
# wget
wget URL # download file
wget -q URL # quiet
wget -r -np URL # recursive, no parent
# SSH / SCP
ssh user@host # connect
ssh -p 2222 user@host # non-default port
ssh -i ~/.ssh/key.pem user@host # private key auth
scp file.txt user@host:/remote/path/ # upload
scp user@host:/remote/file.txt . # download
scp -r dir/ user@host:/remote/ # upload directory
Quick reference: operators and symbols
| Symbol | Meaning |
|---|---|
> |
Redirect stdout (overwrite) |
>> |
Redirect stdout (append) |
2> |
Redirect stderr |
2>&1 |
Redirect stderr to stdout |
| |
Pipe stdout to next command |
&& |
Run next only if previous succeeded |
|| |
Run next only if previous failed |
; |
Run sequentially (regardless of exit code) |
& |
Run in background |
$() |
Command substitution |
${} |
Variable expansion |
$(( )) |
Arithmetic expansion |
[[ ]] |
Extended test (bash only) |
[ ] |
POSIX test |
#! |
Shebang line |
# |
Comment |
6 common mistakes
1. Forgetting quotes around variables
# WRONG — breaks if filename has spaces
rm $file
# CORRECT
rm "$file"
2. [ vs [[ confusion
# WRONG — fails if variable is empty or has spaces
if [ $var == "hello" ]; then
# CORRECT — use double brackets in bash
if [[ "$var" == "hello" ]]; then
3. rm -rf with a variable that could be empty
# DANGEROUS — if $dir is empty, deletes everything from /
rm -rf "$dir/"
# SAFE — check first
[ -n "$dir" ] && rm -rf "$dir/"
4. Parsing ls output
# WRONG — breaks on spaces, newlines in filenames
for f in $(ls); do
# CORRECT
for f in *; do
5. Using exit code as a value
# WRONG — return only exits the function, doesn't return a value
result=$(my_function) # captures stdout, not return code
if my_function; then # checks exit code
# CORRECT — use echo for output, return for status
my_function() { echo "result"; return 0; }
6. cd failure in scripts
# WRONG — script continues in wrong directory if cd fails
cd /some/path
rm -rf * # dangerous!
# CORRECT — abort on failure
cd /some/path || exit 1
rm -rf *
# Or use set -e at the top of the script
set -e
6 FAQ
What's the difference between sh and bash?sh is the POSIX shell standard. bash is a superset with extras: [[, $() arrays, {a..z} ranges, (( )) arithmetic. Use #!/bin/bash for bash features, #!/bin/sh for maximum portability.
How do I make a script stop on any error?
Add at the top: set -euo pipefail. -e exits on error, -u treats unset variables as errors, -o pipefail catches errors in pipes.
How do I run a command in the background and keep it running after logout?nohup command > output.log 2>&1 &. Or use tmux/screen for interactive sessions you can reattach to.
How do I see what a script will do without running it?bash -n script.sh checks syntax without running. bash -x script.sh traces each command as it runs (also use set -x inside scripts).
How do I read input from the user?read -p "Enter name: " name — stores input in $name. Add -s for silent (password) input. Add -t 10 for a 10-second timeout.
What's the fastest way to edit a long command I just typed?
Press Ctrl+X Ctrl+E to open the command in your $EDITOR. Or use fc to edit the last command in your editor and run it.