Claude Code requires a shell to run. If you've never used one before, this guide will get you up to speed. Don't let the terminal stop you — it's simpler than it looks.
What is a shell?
A shell is a program that sits between you and the operating system. You type commands, the shell interprets them, and the OS does the work. That's it.
You → Terminal → Shell → Kernel → Hardware
You type into the terminal (the window). The terminal passes your keystrokes to the shell (bash, zsh, PowerShell). The shell interprets your commands and talks to the kernel — the core of the OS that manages memory, processes, and devices. A graphical desktop does the same thing, but with clicks instead of text.
Why bother?
- Speed — renaming 500 files takes one line, not 500 clicks
- Automation — anything you type once, you can script to repeat forever
- Remote access — servers don't have monitors; the shell is how you talk to them
- Composability — small commands combine into powerful pipelines
Which shell?
| Shell | Where | Notes |
|---|---|---|
bash | Linux (default), macOS (older), WSL | The universal standard. Learn this first. |
zsh | macOS (default since Catalina) | 99% bash-compatible, better tab completion |
PowerShell | Windows (default) | Object-oriented, different syntax. Covered in the comparison tab. |
cmd.exe | Windows (legacy) | Ancient. Avoid it for anything beyond cd and dir. |
Opening a terminal
Before you can type commands, you need to open a terminal — the window that runs your shell. The terminal is the UI; the shell is the language running inside it.
The built-in terminal:
Open Applications → Utilities → Terminal
Better option — install Hyper:
hyper.is
Cross-platform, extensible, looks great.
The shell inside is zsh (macOS default).
It works almost identically to bash.
You'll see a prompt like:
you@mac ~ % _
Open the terminal:
Click the Start button (or press the Win key)
Type "terminal" and press Enter
This opens Windows Terminal (the UI).
The shell inside is PowerShell (the language).
Think of it like: Terminal is to PowerShell
as Terminal.app is to zsh.
You'll see a prompt like:
PS C:\Users\you> _
Keyboard shortcut (most distros):
Ctrl + Alt + T
Or find "Terminal" in your app launcher.
The shell inside is bash (Linux default).
user@machine:~$ _
We recommend Hyper on all platforms:
hyper.is
It's a modern terminal that works on
macOS, Windows, and Linux.
On Windows it runs PowerShell by default.
On macOS/Linux it runs your default shell.
Terminal vs Shell — what's the difference?
The terminal is the window — it handles fonts, colors, tabs, and keyboard input. Examples: Windows Terminal, Terminal.app, Hyper, iTerm2.
The shell is the language running inside that window — it interprets your commands. Examples: bash, zsh, PowerShell.
You can swap either one independently. Run bash inside Windows Terminal, or PowerShell inside Hyper. The terminal is the car; the shell is the engine.
The prompt is just the shell telling you it's ready. The $ or % (or > on PowerShell) means "type here." You don't type the prompt itself — only what comes after it.
Files & Directories
Every OS organizes files in a tree of directories (folders). On macOS and Linux, the top of the tree is called the root, written as /. On Windows, each drive is its own root: C:\.
/ ← root (top of everything)
├── home/
│ └── you/ ← your home directory (~)
│ ├── Documents/
│ ├── Downloads/
│ └── projects/
├── usr/
│ ├── bin/ ← system commands live here
│ └── lib/
├── etc/ ← configuration files
└── tmp/ ← temporary files
C:\ ← root of the C: drive
├── Users\
│ └── you\ ← your home directory (~)
│ ├── Documents\
│ ├── Downloads\
│ └── projects\
├── Program Files\ ← installed programs
├── Windows\
│ └── System32\ ← system commands
└── Temp\ ← temporary files
Unix uses forward slashes: /home/you/Documents
Windows uses backslashes: C:\Users\you\Documents
PowerShell actually accepts both, but backslashes are conventional on Windows.
Pathnames
A path is the address of a file. There are two kinds:
| Type | Starts with | Example |
|---|---|---|
| Absolute | / | /home/you/Documents/notes.txt |
| Relative | anything else | Documents/notes.txt or ./notes.txt (from your current dir) |
Special path shortcuts
| Symbol | Meaning | Example |
|---|---|---|
~ | Your home directory | cd ~ or just cd |
. | Current directory | ./run_this.sh |
.. | Parent directory (one level up) | cd .. |
Navigating
These commands work the same on macOS, Linux, and Windows PowerShell.
$ pwd # where am I?
/home/you
$ ls # what's here?
Documents Downloads projects
$ cd Documents # go into Documents
$ pwd
/home/you/Documents
$ cd .. # go back up
$ pwd
/home/you
$ cd # go home (no argument = home)
PS> pwd # where am I?
C:\Users\you
PS> ls # what's here?
Documents Downloads projects
PS> cd Documents # go into Documents
PS> pwd
C:\Users\you\Documents
PS> cd .. # go back up
PS> pwd
C:\Users\you
PS> cd ~ # go home
Good news: pwd, ls, cd, and cd .. all work in PowerShell too. Microsoft added aliases so the basics feel familiar no matter which shell you're in.
Creating and removing
$ mkdir projects/myapp # create a directory
$ mkdir -p a/b/c # create nested dirs
$ touch notes.txt # create empty file
$ rmdir empty_folder # remove empty dir
$ rm notes.txt # remove a file
$ rm -r projects/myapp # remove dir + contents
PS> mkdir projects/myapp
PS> New-Item a/b/c -ItemType Directory -Force
PS> New-Item notes.txt -ItemType File
PS> Remove-Item empty_folder
PS> Remove-Item notes.txt # or: rm, del
PS> Remove-Item projects/myapp -Recurse
Deleting is permanent. There is no trash can, no undo — in either shell. Double-check before you press Enter.
Copying, moving, renaming
$ cp file.txt backup.txt # copy a file
$ cp -r mydir/ mydir_backup/ # copy a directory
$ mv old.txt new.txt # rename
$ mv file.txt Documents/ # move
PS> Copy-Item file.txt backup.txt
PS> Copy-Item mydir/ mydir_backup/ -Recurse
PS> Move-Item old.txt new.txt # or: mv
PS> Move-Item file.txt Documents/
Both shells overwrite silently. If the destination file already exists, it's gone. In bash use cp -i / mv -i for a prompt. In PowerShell use -Confirm.
Listing files in detail
$ ls -l
drwxr-xr-x 3 you you 4096 Mar 5 10:22 Documents
-rw-r--r-- 1 you you 847 Mar 5 09:11 notes.txt
$ ls -la # include hidden files
$ ls -lh # human-readable sizes
PS> Get-ChildItem
Mode LastWriteTime Length Name
d---- 3/5/2026 10:22 AM Documents
-a--- 3/5/2026 9:11 AM 847 notes.txt
PS> Get-ChildItem -Force # include hidden
PS> Get-ChildItem | Format-Table Name,Length -Auto
Reading the output
bash ls -l: first character is d (directory), - (file), or l (link), followed by permissions, owner, group, size, date, name.
PowerShell Get-ChildItem: Mode column shows d (directory), a (archive), r (read-only), h (hidden), s (system).
Essential Commands
These are the commands you'll use every day. Each one does one thing well. Every section shows bash on the left and the PowerShell equivalent on the right.
Reading files
$ cat file.txt # print entire file
$ head file.txt # first 10 lines
$ head -n 3 file.txt # first 3 lines
$ tail file.txt # last 10 lines
$ tail -f log.txt # follow a file (watch it grow)
$ less file.txt # scroll through (q to quit)
PS> Get-Content file.txt # or: cat file.txt
PS> Get-Content file.txt -Head 10
PS> Get-Content file.txt -Head 3
PS> Get-Content file.txt -Tail 10
PS> Get-Content log.txt -Wait # follow
PS> Get-Content file.txt | Out-Host -Paging
Searching
$ grep "hello" file.txt
$ grep -i "hello" file.txt # case-insensitive
$ grep -r "TODO" src/ # recursive
$ grep -n "error" log.txt # line numbers
$ find . -name "*.txt" # find by name
$ find . -type d # dirs only
$ find /tmp -size +100M # large files
PS> Select-String "hello" file.txt
PS> Select-String "hello" file.txt -CaseSensitive:$false
PS> Get-ChildItem src/ -Recurse | Select-String "TODO"
PS> Select-String "error" log.txt # shows line numbers by default
PS> Get-ChildItem -Recurse -Filter "*.txt"
PS> Get-ChildItem -Recurse -Directory
PS> Get-ChildItem /tmp -Recurse | Where-Object {$_.Length -gt 100MB}
Counting and sorting
$ wc file.txt # lines, words, chars
12 84 527 file.txt
$ wc -l file.txt # line count only
$ sort names.txt # alphabetical
$ sort -n numbers.txt # numeric
$ sort -r names.txt # reverse
$ uniq sorted.txt # deduplicate
$ sort names.txt | uniq # sort then deduplicate
PS> Get-Content file.txt | Measure-Object -Line -Word -Character
Lines: 12 Words: 84 Characters: 527
PS> (Get-Content file.txt).Count # line count
PS> Get-Content names.txt | Sort-Object
PS> Get-Content nums.txt | Sort-Object {[int]$_}
PS> Get-Content names.txt | Sort-Object -Descending
PS> Get-Content sorted.txt | Get-Unique
PS> Get-Content names.txt | Sort-Object | Get-Unique
Text manipulation
$ cut -d',' -f1 data.csv # first CSV column
$ tr 'a-z' 'A-Z' < file.txt # uppercase
$ tr -d ' ' < file.txt # delete spaces
$ sed 's/old/new/g' file.txt # replace (print)
$ sed -i 's/old/new/g' file.txt # replace (in place)
PS> Import-Csv data.csv | Select-Object -First 1
# or for raw split:
PS> (Get-Content data.csv) -split ',' | Select-Object -Index 0
PS> (Get-Content file.txt).ToUpper()
PS> (Get-Content file.txt) -replace ' ',''
PS> (Get-Content file.txt) -replace 'old','new'
PS> (Get-Content file.txt) -replace 'old','new' | Set-Content file.txt
System info
$ date # date and time
$ whoami # your username
$ hostname # machine name
$ uname -a # OS info
$ df -h # disk space
$ du -sh * # size of each item
$ ps aux # running processes
$ top # live monitor (q quits)
PS> Get-Date
PS> $env:USERNAME # or: whoami
PS> $env:COMPUTERNAME # or: hostname
PS> Get-ComputerInfo | Select-Object OsName,OsVersion
PS> Get-PSDrive -PSProvider FileSystem
PS> Get-ChildItem | ForEach-Object { "{0,10} {1}" -f ($_.Length/1MB).ToString("0.0MB"), $_.Name }
PS> Get-Process # or: ps
PS> # no built-in top; use Task Manager or:
PS> while($true){Get-Process | Sort-Object CPU -Desc | Select-Object -First 10; Start-Sleep 2; Clear-Host}
Getting help
$ man ls # manual page (q quits)
$ ls --help # quick help (Linux)
$ which python # where is this command?
$ type cd # builtin or program?
PS> Get-Help Get-ChildItem # help page
PS> Get-Help Get-ChildItem -Examples # just examples
PS> Get-Command python # where is it?
PS> Get-Command cd | Select-Object CommandType
Input, Output & Pipes
Every command has three channels, and you can rewire them. This works in both bash and PowerShell.
The three channels
| Channel | Name | Number | Default |
|---|---|---|---|
| stdin | Standard input | 0 | Keyboard |
| stdout | Standard output | 1 | Screen |
| stderr | Standard error | 2 | Screen |
Output redirection
$ echo "hello" > file.txt # write (overwrites!)
$ echo "world" >> file.txt # append
$ cat file.txt
hello
world
$ ls /nope 2> errors.txt # errors only
$ command &> all.txt # both stdout+stderr
PS> "hello" | Out-File file.txt # write
PS> "world" | Out-File file.txt -Append # append
PS> Get-Content file.txt
hello
world
PS> Get-Item /nope 2> errors.txt # same syntax!
PS> command *> all.txt # all streams
> overwrites. If the file exists, its contents are destroyed. Use >> (bash) or -Append (PowerShell) to add to the end.
Input redirection
$ wc -l < file.txt # feed file to stdin
2
$ sort < unsorted.txt > sorted.txt
# PowerShell doesn't use < for input.
# Instead, pipe file content in:
PS> (Get-Content file.txt).Count # line count
2
PS> Get-Content unsorted.txt | Sort-Object | Out-File sorted.txt
Pipes
The | character connects the output of one command to the input of the next. This works in both shells — it's how small tools compose into powerful workflows.
# How many users are logged in?
$ who | wc -l
5
# How many files here?
$ ls | wc -l
12
# 5 largest files
$ du -sh * | sort -rh | head -5
# Word frequency in a file
$ tr ' ' '\n' < book.txt | sort | uniq -c | sort -rn | head -10
# Error timestamps from logs
$ grep "ERROR" app.log | cut -d' ' -f1,2 | sort | uniq -c
# How many processes running?
PS> Get-Process | Measure-Object
Count: 142
# How many files here?
PS> (Get-ChildItem).Count
12
# 5 largest files
PS> Get-ChildItem | Sort-Object Length -Desc | Select-Object -First 5 Name,Length
# Word frequency in a file
PS> (Get-Content book.txt) -split '\s+' | Group-Object | Sort-Object Count -Desc | Select-Object -First 10
# Error timestamps from logs
PS> Select-String "ERROR" app.log | ForEach-Object { $_.Line.Split(' ')[0..1] -join ' ' } | Group-Object | Sort-Object Count -Desc
The pipeline philosophy
Both shells share the same idea: small commands chained together. Bash pipes text — each command parses and emits strings. PowerShell pipes objects — each command passes structured data with typed properties. The concept is the same; the data format differs.
Filters
A filter is any command that reads input and writes output. These work in pipes:
| Task | bash filter | PowerShell equivalent |
|---|---|---|
| Sort | sort | Sort-Object |
| Deduplicate | uniq | Get-Unique or Group-Object |
| Search text | grep | Select-String or Where-Object |
| First / last N | head / tail | Select-Object -First / -Last |
| Count | wc | Measure-Object |
| Extract columns | cut | Select-Object (by property) |
| Transform chars | tr | -replace operator |
| Find/replace | sed | -replace or ForEach-Object |
| Pattern processing | awk | ForEach-Object with -split |
How They Differ
By now you've seen the side-by-side commands in every section. This page covers the conceptual differences and the topics not covered elsewhere: variables, environment, and process management.
PowerShell aliases: Microsoft added familiar names like ls, cat, cp, mv, rm as aliases for PowerShell cmdlets. They mostly work, but the flags are different. When in doubt, use the native cmdlet name.
The big difference: text vs objects
Unix shells pass text. PowerShell passes objects.
Unix: Every command outputs a stream of text. You slice it with cut, filter it with grep, and sort it with sort. If the output format changes (an extra column, a different date format), your pipeline breaks.
PowerShell: Commands output .NET objects with typed properties. Get-Process returns Process objects with .CPU, .Id, .Name. You filter with Where-Object and pick fields with Select-Object. The output format can change without breaking your pipeline.
# Get PIDs of node processes
$ ps aux | grep node | awk '{print $2}'
1234
5678
# Fragile: depends on column position
# Get PIDs of node processes
PS> Get-Process node | Select-Object Id
1234
5678
# Robust: .Id is a typed property
Naming conventions
Cryptic vs Discoverable
Unix: short, lowercase, cryptic — ls, grep, awk, sed, wc, chmod. You memorize them.
PowerShell: Verb-Noun, explicit — Get-ChildItem, Select-String, Measure-Object, Set-ItemProperty. You discover them:
PS> Get-Command *process* # find all process-related commands
PS> Get-Command -Verb Set # all commands that set something
PS> Get-Command -Noun Item # all commands about items (files, etc.)
Variables & environment
$ NAME="world" # no spaces around =
$ echo "hello $NAME"
$ echo $HOME # env variable
$ echo $PATH
$ export API_KEY="secret" # set for child processes
$ env # list all env vars
# Command substitution
$ TODAY=$(date +%Y-%m-%d)
$ echo "Today is $TODAY"
PS> $NAME = "world" # spaces OK
PS> "hello $NAME"
PS> $HOME # built-in variable
PS> $env:PATH # env: prefix
PS> $env:API_KEY = "secret"
PS> Get-ChildItem env: # list all env vars
# Command substitution
PS> $TODAY = Get-Date -Format "yyyy-MM-dd"
PS> "Today is $TODAY"
Process management
$ ps aux # all processes
$ ps aux | grep node # find by name
$ kill 1234 # graceful stop
$ kill -9 1234 # force kill
$ command & # run in background
$ jobs # list bg jobs
$ fg # bring to foreground
PS> Get-Process
PS> Get-Process | Where-Object {$_.Name -like "node*"}
PS> Stop-Process -Id 1234
PS> Stop-Process -Id 1234 -Force
PS> Start-Job { command } # background
PS> Get-Job # list bg jobs
PS> Receive-Job -Id 1 # get output
Keyboard & Shortcuts
You don't need a mouse in the terminal. These shortcuts will save you a huge amount of time once they become muscle memory.
Tab completion
The most important shortcut you'll learn
Start typing a filename or command and press Tab. The shell will complete it for you. If there are multiple matches, press Tab twice to see all options.
$ cd Doc[Tab]
$ cd Documents/ # completed!
$ git sta[Tab]
$ git status # completed!
$ ls *.tx[Tab]
file.txt notes.txt readme.txt # multiple matches shown
PS> cd Doc[Tab]
PS> cd .\Documents\ # completed!
PS> Get-Chi[Tab]
PS> Get-ChildItem # completed!
# Keep pressing Tab to cycle through matches
PS> Get-Com[Tab][Tab][Tab]
Command history
Every command you type is saved. Use the arrow keys to scroll through your history instead of retyping.
Up # previous command
Down # next command
Ctrl+R # search history (type to filter)
$ history # show full history list
$ !grep # re-run last command starting with "grep"
$ !! # re-run the very last command
Up # previous command
Down # next command
Ctrl+R # search history (same!)
PS> Get-History # show full history
PS> Invoke-History 5 # re-run command #5
F8 # search history by prefix
Ctrl+R is a game changer. Press it, then start typing any part of a previous command. It fuzzy-matches your history in real time. Press Ctrl+R again to cycle through older matches. Press Enter to run it, or Esc to cancel.
Cursor movement
Move around the current line without using the mouse.
| Keys | Action | Works in |
|---|---|---|
Ctrl+A | Jump to beginning of line | bash, zsh, PowerShell |
Ctrl+E | Jump to end of line | bash, zsh, PowerShell |
Left / Right | Move cursor one character | all |
Alt+B / Alt+F | Move cursor one word back / forward | bash, zsh |
Ctrl+Left / Right | Move cursor one word | PowerShell, zsh |
Home | Beginning of line | all |
End | End of line | all |
Editing the line
Delete and cut text without reaching for the mouse.
| Keys | Action | Works in |
|---|---|---|
Ctrl+K | Delete from cursor to end of line | bash, zsh, PowerShell |
Ctrl+U | Delete from cursor to beginning of line | bash, zsh, PowerShell |
Ctrl+W | Delete the previous word | bash, zsh |
Alt+D | Delete the next word | bash, zsh |
Ctrl+Y | Paste back what Ctrl+K/U/W deleted | bash, zsh |
Backspace | Delete character before cursor | all |
Delete | Delete character after cursor | all |
Ctrl+K + Ctrl+Y is "cut and paste" for the command line. Jump to a position with Ctrl+A, kill the rest with Ctrl+K, move somewhere else, paste it back with Ctrl+Y. Faster than selecting with the mouse.
Control commands
| Keys | Action | Works in |
|---|---|---|
Ctrl+C | Cancel the current command | all |
Ctrl+D | Exit the shell (or signal end-of-input) | bash, zsh |
Ctrl+L | Clear the screen | all |
Ctrl+Z | Suspend current process (resume with fg) | bash, zsh |
Ctrl+S | Pause output (freezes terminal) | bash, zsh |
Ctrl+Q | Resume output (unfreeze) | bash, zsh |
If your terminal freezes and nothing you type shows up, you probably hit Ctrl+S by accident. Press Ctrl+Q to unfreeze it. This trips up everyone at least once.
Copy & paste in the terminal
Cmd+C # copy selected text
Cmd+V # paste
# In iTerm2 / Hyper:
# Select text to auto-copy
# Middle-click or Cmd+V to paste
Ctrl+Shift+C # copy (not Ctrl+C!)
Ctrl+Shift+V # paste
# Or: select text, right-click to copy
# Right-click again to paste
# Ctrl+C in a terminal means "cancel"
# so copy needs the Shift modifier
First Scripts
A shell script is just a text file containing commands. Instead of typing them one at a time, you save them and run the file.
Hello World
#!/bin/bash
# first argument passed to the script
NAME=$1
if [ -z "$NAME" ]; then
echo "Usage: ./greet.sh <name>"
exit 1
fi
echo "Hello, $NAME!"
echo "Today is $(date +%A)."
echo "You are in $(pwd)."
# first argument passed to the script
param([string]$Name)
if (-not $Name) {
Write-Host "Usage: .\greet.ps1 <name>"
exit 1
}
Write-Host "Hello, $Name!"
Write-Host "Today is $((Get-Date).DayOfWeek)."
Write-Host "You are in $(Get-Location)."
Running it
$ chmod +x greet.sh # make executable (once)
$ ./greet.sh Alice
Hello, Alice!
Today is Thursday.
You are in /home/you.
# no chmod needed on Windows
PS> .\greet.ps1 -Name Alice
Hello, Alice!
Today is Thursday.
You are in C:\Users\you.
The shebang line
Bash scripts start with #!/bin/bash — this tells the OS which program should interpret the file. PowerShell scripts use the .ps1 extension instead; Windows knows to run them with PowerShell.
Variables
GREETING="Hello"
NAME="World"
echo "$GREETING, $NAME!"
# Command substitution
TODAY=$(date +%Y-%m-%d)
FILES=$(ls | wc -l)
echo "Date: $TODAY, Files: $FILES"
# WRONG — no spaces around =
# NAME = "bad" <-- error!
$greeting = "Hello"
$name = "World"
"$greeting, $name!"
# Command substitution
$today = Get-Date -Format "yyyy-MM-dd"
$files = (Get-ChildItem).Count
"Date: $today, Files: $files"
# Spaces around = are fine
# $name = "good" <-- works!
Conditionals
FILE=$1
if [ -f "$FILE" ]; then
echo "$FILE is a file."
echo "$(wc -l < "$FILE") lines"
elif [ -d "$FILE" ]; then
echo "$FILE is a directory."
else
echo "$FILE does not exist."
fi
$file = $args[0]
if (Test-Path $file -PathType Leaf) {
"$file is a file."
"$((Get-Content $file).Count) lines"
} elseif (Test-Path $file -PathType Container) {
"$file is a directory."
} else {
"$file does not exist."
}
Test operators
| What | bash | PowerShell |
|---|---|---|
| File exists | [ -e file ] | Test-Path file |
| Is a file | [ -f file ] | Test-Path file -PathType Leaf |
| Is a directory | [ -d file ] | Test-Path file -PathType Container |
| String empty | [ -z "$var" ] | -not $var or [string]::IsNullOrEmpty($var) |
| Strings equal | [ "$a" = "$b" ] | $a -eq $b |
| Numbers equal | [ $a -eq $b ] | $a -eq $b |
| Less than | [ $a -lt $b ] | $a -lt $b |
| Greater than | [ $a -gt $b ] | $a -gt $b |
Loops
# Loop over a list
for fruit in apple banana cherry; do
echo "I like $fruit"
done
# Loop over files
for f in *.txt; do
echo "$f: $(wc -l < "$f") lines"
done
# Loop with numbers
for i in $(seq 1 5); do
echo "Count: $i"
done
# While loop
COUNT=0
while [ $COUNT -lt 5 ]; do
echo "Tick: $COUNT"
COUNT=$((COUNT + 1))
done
# Loop over a list
foreach ($fruit in "apple","banana","cherry") {
"I like $fruit"
}
# Loop over files
foreach ($f in Get-ChildItem *.txt) {
"$($f.Name): $((Get-Content $f).Count) lines"
}
# Loop with numbers
1..5 | ForEach-Object {
"Count: $_"
}
# While loop
$count = 0
while ($count -lt 5) {
"Tick: $count"
$count++
}
Practical example: backup script
#!/bin/bash
SOURCE=$1
if [ -z "$SOURCE" ] || [ ! -d "$SOURCE" ]; then
echo "Usage: ./backup.sh <dir>"
exit 1
fi
TS=$(date +%Y%m%d_%H%M%S)
BACKUP="${SOURCE}_backup_${TS}.tar.gz"
tar czf "$BACKUP" "$SOURCE"
SIZE=$(du -h "$BACKUP" | cut -f1)
echo "Backed up to $BACKUP ($SIZE)"
param([Parameter(Mandatory)]
[string]$Source)
if (-not (Test-Path $Source -PathType Container)) {
Write-Error "Not found: $Source"
exit 1
}
$ts = Get-Date -Format "yyyyMMdd_HHmmss"
$backup = "${Source}_backup_${ts}.zip"
Compress-Archive -Path $Source -DestinationPath $backup
$mb = [math]::Round((Get-Item $backup).Length/1MB, 1)
"Backed up to $backup ($mb MB)"
Quick Reference
Navigation
| Task | bash / zsh | PowerShell |
|---|---|---|
| Where am I? | pwd | Get-Location |
| Go to directory | cd path | Set-Location path |
| Go home | cd or cd ~ | cd ~ |
| Go up one level | cd .. | cd .. |
| List files | ls | Get-ChildItem |
| List all (hidden too) | ls -la | Get-ChildItem -Force |
Files
| Task | bash / zsh | PowerShell |
|---|---|---|
| Read file | cat file | Get-Content file |
| Create file | touch file | New-Item file |
| Copy | cp src dst | Copy-Item src dst |
| Move / rename | mv src dst | Move-Item src dst |
| Delete file | rm file | Remove-Item file |
| Delete directory | rm -r dir | Remove-Item dir -Recurse |
| Create directory | mkdir dir | New-Item dir -ItemType Directory |
Search & filter
| Task | bash / zsh | PowerShell |
|---|---|---|
| Search file content | grep pattern file | Select-String pattern file |
| Find files by name | find . -name "*.txt" | Get-ChildItem -Recurse -Filter *.txt |
| Sort lines | sort file | Get-Content file | Sort-Object |
| Count lines | wc -l file | (Get-Content file).Count |
| Unique lines | sort | uniq | Sort-Object | Get-Unique |
| First N lines | head -n 5 file | Get-Content file -Head 5 |
| Last N lines | tail -n 5 file | Get-Content file -Tail 5 |
I/O & pipes
| Task | bash / zsh | PowerShell |
|---|---|---|
| Write to file | cmd > file | cmd | Out-File file |
| Append to file | cmd >> file | cmd | Out-File file -Append |
| Pipe | cmd1 | cmd2 | cmd1 | cmd2 |
| Discard output | cmd > /dev/null | cmd | Out-Null |
| Redirect errors | cmd 2> file | cmd 2> file |
System
| Task | bash / zsh | PowerShell |
|---|---|---|
| Current user | whoami | $env:USERNAME |
| Date/time | date | Get-Date |
| Running processes | ps aux | Get-Process |
| Kill process | kill PID | Stop-Process -Id PID |
| Disk space | df -h | Get-PSDrive |
| Get help | man cmd | Get-Help cmd |
| Clear screen | clear | Clear-Host or cls |
| Command history | history | Get-History |
Keyboard shortcuts (work in both)
| Keys | Action |
|---|---|
Ctrl+C | Stop the current command |
Ctrl+L | Clear the screen |
Tab | Auto-complete file/command names |
Up / Down | Previous / next command in history |
Ctrl+R | Search command history (bash) |
Ctrl+A | Jump to start of line (bash) |
Ctrl+E | Jump to end of line (bash) |
Wildcards (globbing)
| Pattern | Matches | Example |
|---|---|---|
* | Any number of characters | *.txt → all .txt files |
? | Exactly one character | file?.txt → file1.txt, fileA.txt |
[abc] | One of a, b, or c | [Mm]akefile |
[0-9] | One digit | log[0-9].txt |