PowerShell Essentials¶
The modern Windows shell. Unlike CMD, PowerShell pipes objects, not text:
Get-Process python | Stop-Processfilters and acts on real data. If you do serious Windows automation, this is your shell.
Table of Contents¶
- Installation / Setup
- Core Syntax
- Common Operations
- Practical Examples
- Common Patterns
- Best Practices
- Common Mistakes
- Troubleshooting
- Related Cheat Sheets
- Official Documentation
Installation / Setup¶
Windows 10/11 ships PowerShell 5.1 (Windows PowerShell) and pwsh 7+ (PowerShell Core, installable) — prefer 7+. Open via Terminal, or:
pwsh # PowerShell 7
$PSVersionTable.PSVersion # version
Get-Command -Name *process* # discover cmdlets
Get-Help Get-Process # docs (add -Online for web)
CMD vs PowerShell in one glance: CMD is text + %VAR% + copy; PowerShell is objects + $VAR + Copy-Item. Most "verbs" come from the standard verb list: Get-, Set-, New-, Remove-, Start-, Stop-, Test-.
Core Syntax¶
Linux ↔ Windows (PowerShell) map¶
| Task | Linux | PowerShell (alias) | CMD |
|---|---|---|---|
| list files | ls -la |
Get-ChildItem (ls, dir) |
dir |
| change dir | cd /data |
Set-Location (cd) |
cd |
| print dir | pwd |
Get-Location (pwd) |
cd |
| copy | cp -r a b |
Copy-Item -Recurse a b (cp) |
copy |
| move/rename | mv a b |
Move-Item (mv) / Rename-Item |
move/ren |
| delete | rm -r f |
Remove-Item -Recurse -Force (rm, del) |
del, rmdir |
| view file | cat f |
Get-Content (cat, type) |
type |
| tail | tail -f f |
Get-Content f -Tail 20 -Wait |
— |
| find text | grep |
Select-String (grep) |
findstr |
| env var | echo $VAR |
$env:VAR / Get-ChildItem Env: |
%VAR% |
| kill proc | kill PID |
Stop-Process -Id 1234 (kill) |
taskkill |
| which | which cmd |
Get-Command cmd (gcm) |
where |
Objects & pipelines (the big idea)¶
Get-Process python # process objects, not text
Get-Process | Where-Object CPU -gt 10 # filter objects (like grep on steroids)
Get-Process | Sort-Object CPU -Descending | Select-Object -First 5
Get-Process | Select-Object Name, Id, CPU | Export-Csv procs.csv
Pipeline stages operate on objects with properties — you filter/sort/select properties, not lines.
Variables, arrays, hashes¶
$name = "Ada"
$count = 42
$files = Get-ChildItem *.csv # array of objects
$files.Count
$config = @{ lr = 0.01; epochs = 10 } # hashtable (dict)
$config["lr"]
$env:PATH # environment: $env: prefix
$env:MY_VAR = "value" # session only
[Environment]::SetEnvironmentVariable("MY_VAR", "value", "User") # persistent
Common Operations¶
Navigation & files¶
ls -Force # include hidden
ls -Recurse -Filter *.py
Get-Content app.log -Tail 50 # last 50 lines
Get-Content app.log -Wait # follow like tail -f
Select-String -Path *.log -Pattern "error" -CaseSensitive:$false
Processes, services & system¶
Get-Process # tasklist equivalent
Get-Process python | Stop-Process # kill all python
Stop-Process -Id 1234 -Force
Get-Service # services
Get-Service sshd | Start-Service
Restart-Service docker
Get-ComputerInfo # OS/hardware overview
Get-CimInstance Win32_OperatingSystem # detailed OS info
Networking¶
Test-NetConnection google.com -Port 443 # ping + port check (great)
Get-NetTCPConnection -LocalPort 8888 # who listens on 8888
Get-NetTCPConnection -LocalPort 8888 | Select-Object -ExpandProperty OwningProcess
Invoke-WebRequest https://example.com -OutFile page.html # curl-ish
Invoke-RestMethod https://api.github.com/repos/python/cpython | ConvertTo-Json
Packages (winget & chocolatey)¶
winget install Python.Python.3.12 # modern installer
winget upgrade --all
winget search pandas
# classic: choco install python --yes (after installing chocolatey)
Archives & downloads¶
SSH¶
ssh user@host # OpenSSH client ships with Windows
ssh-keygen -t ed25519
Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub # copy into GitHub/cloud
scp -i $env:USERPROFILE\.ssh\id_ed25519 model.pt user@host:/home/user/
Text vs JSON handling¶
Get-Content data.json | ConvertFrom-Json | Select-Object -ExpandProperty results
$obj = Get-Content data.json | ConvertFrom-Json
$obj | ConvertTo-Json -Depth 5 | Set-Content out.json
Practical Examples¶
1. Find and stop the process holding port 8888¶
$conn = Get-NetTCPConnection -LocalPort 8888 -ErrorAction SilentlyContinue
if ($conn) {
$pid = $conn.OwningProcess
"Killing PID $pid ($((Get-Process -Id $pid).Name))"
Stop-Process -Id $pid -Force
} else {
"port 8888 is free"
}
2. Export a directory listing to CSV for analysis¶
Get-ChildItem data -Recurse -File | Select-Object Name, Length, LastWriteTime |
Export-Csv file_inventory.csv -NoTypeInformation
Import-Csv file_inventory.csv | Where-Object Length -gt 1MB
3. Loop a training command over configs¶
foreach ($lr in 0.001, 0.0001) {
foreach ($seed in 1, 2, 3) {
Start-Process python -ArgumentList "train.py", "--lr", "$lr", "--seed", "$seed" -NoNewWindow
Start-Sleep -Seconds 2
}
}
4. Health check then restart a service¶
if (-not (Test-NetConnection localhost -Port 8000 -InformationLevel Quiet)) {
Restart-Service myapi
"service restarted"
} else { "service healthy" }
Common Patterns¶
# Fail-fast script header
$ErrorActionPreference = "Stop"
# Cross-platform one-liner spirit: every stage transforms objects
Get-ChildItem logs -Filter *.log | ForEach-Object {
$n = (Select-String -Path $_.FullName -Pattern "ERROR").Count
[PSCustomObject]@{ File = $_.Name; Errors = $n }
} | Where-Object Errors -gt 0 | Sort-Object Errors -Descending
# Try/catch like other languages
try { Invoke-RestMethod $url } catch { Write-Warning "failed: $_" }
Best Practices¶
- Pipe objects, not text — you almost never need
format-tablemid-pipeline. - Use
-ErrorAction Stopin scripts so failures don't pass silently. - Learn the aliases but type the cmdlets in scripts for readability.
- Prefer
Get-Content -Tailover loading whole log files. - Restrict script execution thoughtfully: check
Get-ExecutionPolicy; run trusted scripts with-ExecutionPolicy Bypass -File x.ps1only when you understand them. - Windows security defaults block unsigned scripts (
ExecutionPolicy) — that's by design; sign or explicitly allow your own. - Keep read-only commands (
Get-*,Test-NetConnection,Select-String) for probing systems you don't own; never runStop-Process/Remove-Itemagainst machines without authorization.
Common Mistakes¶
| Mistake | Consequence | Fix |
|---|---|---|
Using CMD syntax (%VAR%, copy) |
Literal text / wrong commands | $VAR, Copy-Item |
Get-Content on a huge file |
Slow, memory-heavy | -Tail N or -ReadCount |
Forgetting Select-Object |
Terminal flooded with objects | Select just the properties you need |
where.exe confusion |
where alias ≠ expected |
Use Get-Command |
Unquoted *.csv in some contexts |
Unexpected glob expansion | Quote patterns for -Filter/-Path |
Stop-Process without checking |
Kills the wrong app | Filter first: Get-Process \| Where-Object ... |
Editing $PATH in one session |
Lost on restart | Use [Environment]::SetEnvironmentVariable(..., "User") |
Pipelines through Out-String to parse |
Text-regex hell | Stay in object space |
Troubleshooting¶
| Symptom | Cause | Fix |
|---|---|---|
... is not recognized as a cmdlet |
Typo or not installed | Get-Command <name>; check module/path |
Access denied |
Needs elevation | Run PowerShell as administrator |
| Scripts won't run | ExecutionPolicy | Get-ExecutionPolicy; Set-ExecutionPolicy -Scope CurrentUser RemoteSigned |
| Output cut off | Console width | Select-Object fewer properties or Format-List |
Invoke-RestMethod TLS error |
Old TLS default | [Net.ServicePointManager]::SecurityProtocol = 'Tls12' |
| Can't find python after install | PATH not refreshed | New terminal; $env:Path refresh or setx |
Related Cheat Sheets¶
- Windows CMD — the legacy shell and CMD-specific commands
- WSL — full Linux on Windows when you prefer bash
- linux-commands.md — find the Linux twin of any command
- bash.md — scripting comparisons
- Home · Central Navigation Index
Official Documentation¶
- PowerShell documentation (Microsoft)
- PowerShell 7 installation
- PowerShell reference (ss64)
- About Execution Policies
Last Updated¶
2026-09-06 — Initial version.