Skip to main content

PowerShell

Personal reference notes on PowerShell: core concepts, syntax, and the cmdlets I reach for most often. For copy-paste project/file scripts I actually use, see Terminal Commands.

Related

See Linux for the Unix/bash equivalent of this page.

Core Concepts

  • Object pipeline — unlike bash, PowerShell pipes pass full .NET objects, not plain text. Get-Process | Sort-Object CPU sorts on the actual CPU property, no text parsing needed.
  • Verb-Noun naming — cmdlets follow a Verb-Noun pattern (Get-Item, Set-Location, Remove-Item). Verbs are standardized; run Get-Verb to see the approved list.
  • Case-insensitive — commands, parameters, and most comparisons are case-insensitive by default.
  • EditionsWindows PowerShell (5.1, built into Windows, powershell.exe) vs. PowerShell 7+ (cross-platform, pwsh.exe, actively developed). New scripts should target 7+.
  • Providers — PowerShell exposes things like the filesystem, registry, and certificate store as navigable "drives" (cd HKLM:\, cd Cert:\).

Getting Help

Get-Help Get-Process # help for a cmdlet
Get-Help Get-Process -Examples # just usage examples
Get-Help Get-Process -Full # full help incl. parameters
Update-Help # refresh local help files (run as admin)
Get-Command # list all available commands
Get-Command -Verb Get # list commands with a given verb
Get-Command -Noun Process # list commands with a given noun
Get-Member # inspect an object's properties/methods
Get-Process | Get-Member # see what properties/methods a Process object exposes

Variables & Types

$name = "Alice" # string
$count = 5 # int
$items = @("a", "b", "c") # array
$map = @{ key = "value" } # hashtable
$true / $false # booleans
$null # null

$name.GetType() # inspect the underlying .NET type
[int]"42" # cast to int
[string]42 # cast to string

String interpolation uses double quotes only:

"Hello, $name!" # interpolates
'Hello, $name!' # literal — single quotes do not interpolate

Comparison & Logical Operators

PowerShell doesn't use ==, !=, <, > for comparisons — it uses named operators:

OperatorMeaning
-eqequal
-nenot equal
-gt / -ltgreater / less than
-ge / -legreater-or-equal / less-or-equal
-likewildcard match (*, ?)
-matchregex match
-containscollection contains value
-invalue is in collection
-and / -or / -notlogical operators
if ($count -gt 3 -and $name -eq "Alice") { "match" }
Get-ChildItem | Where-Object { $_.Name -like "*.log" }

Control Flow

if ($x -eq 1) { "one" } elseif ($x -eq 2) { "two" } else { "other" }

foreach ($item in $items) { Write-Host $item }

for ($i = 0; $i -lt 5; $i++) { Write-Host $i }

$i = 0
while ($i -lt 5) { $i++ }

switch ($value) {
1 { "one" }
2 { "two" }
default { "other" }
}

Functions & Scripts

function Get-Square {
param([int]$Number)
return $Number * $Number
}

Get-Square -Number 4 # 16
# Run a script
.\script.ps1

# Pass arguments
.\script.ps1 -Path "C:\data" -Verbose

Execution Policy

Controls whether scripts are allowed to run (a safety feature, not real security).

Get-ExecutionPolicy # check current policy
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser # common dev-friendly setting

Common values: Restricted (default, no scripts), RemoteSigned (local scripts run, downloaded ones need a signature), Unrestricted, Bypass.

Profile (like .bashrc)

$PROFILE # path to your profile script
Test-Path $PROFILE # check if it exists
notepad $PROFILE # edit it
. $PROFILE # reload it in the current session

Use it for aliases, functions, and env vars you want in every session.

Common Cmdlets by Category

Filesystem

Get-ChildItem # list directory contents (alias: ls, dir, gci)
Get-ChildItem -Recurse -File # list files recursively
Set-Location C:\path # change directory (alias: cd)
Get-Location # print working directory (alias: pwd)
New-Item -ItemType Directory name # mkdir
New-Item -ItemType File name.txt # touch
Copy-Item src dest -Recurse # cp
Move-Item old new # mv / rename
Remove-Item path -Recurse -Force # rm -rf
Test-Path path # check if a path exists
Rename-Item old.txt new.txt # rename a file

Content / Text

Get-Content file.txt # cat
Get-Content file.txt -Tail 20 # tail
Get-Content file.txt -Wait -Tail 20 # tail -f (follow)
Set-Content file.txt "text" # overwrite file contents
Add-Content file.txt "text" # append to file
Select-String "pattern" file.txt # grep
Select-String "pattern" -Path *.log -Recurse # recursive grep
(Get-Content file.txt) -replace "foo","bar" |
Set-Content file.txt # sed-style replace

Processes & Services

Get-Process # ps aux
Get-Process -Name chrome # filter by name
Stop-Process -Name chrome # kill by name
Stop-Process -Id 1234 # kill by PID
Start-Process notepad.exe # launch a process
Get-Service # list services
Get-Service -Name wuauserv # filter by name
Start-Service / Stop-Service / Restart-Service # control a service

Filtering, Sorting, Selecting (the real power of the pipeline)

Get-Process | Sort-Object CPU -Descending
Get-Process | Where-Object { $_.CPU -gt 100 }
Get-Process | Select-Object Name, Id, CPU -First 10
Get-ChildItem | Group-Object Extension
Get-ChildItem | Measure-Object -Property Length -Sum
Get-Process | ForEach-Object { $_.Name }

System Info

Get-ComputerInfo # OS/hardware summary
$PSVersionTable # PowerShell version info
Get-CimInstance Win32_OperatingSystem # detailed OS info (modern replacement for Get-WmiObject)
Get-Disk / Get-Volume # disk info
Get-EventLog -LogName System -Newest 20 # recent system events (Windows PowerShell)
Get-WinEvent -LogName System -MaxEvents 20 # recent system events (PS7+)

Networking

Test-Connection host # ping
Test-NetConnection host -Port 443 # test a specific port
Resolve-DnsName domain.com # DNS lookup
Get-NetIPAddress # show IP addresses
Get-NetAdapter # list network adapters
Invoke-WebRequest https://example.com # curl-like HTTP request
Invoke-RestMethod https://api.example.com # fetch + auto-parse JSON

Modules & Packages

Get-Module -ListAvailable # list installed modules
Install-Module ModuleName # install from PowerShell Gallery
Import-Module ModuleName # load a module into the session
Find-Module keyword # search the gallery

Remoting

Enter-PSSession -ComputerName remotehost # interactive remote session
Invoke-Command -ComputerName remotehost -ScriptBlock { Get-Process }
New-PSSession -ComputerName remotehost # persistent session object

Aliases Cheat Sheet

Many familiar Unix/cmd names are actually aliases for PowerShell cmdlets:

AliasReal Cmdlet
ls, dirGet-ChildItem
cdSet-Location
pwdGet-Location
cat, typeGet-Content
cp, copyCopy-Item
mv, moveMove-Item
rm, del, eraseRemove-Item
psGet-Process
killStop-Process
curl, wgetInvoke-WebRequest
echoWrite-Output
cls, clearClear-Host
historyGet-History
man, helpGet-Help
Get-Alias ls # see what an alias actually maps to
Get-Alias -Definition Get-ChildItem # find all aliases for a cmdlet

Redirection & Pipes

command > file # redirect output, overwrite
command >> file # append
command 2> file # redirect errors (stream 2)
command 2>&1 # merge error stream into output
command | Out-Null # discard output
command | Tee-Object file.txt # write to file AND pass through

Things I Keep Forgetting

  • Single quotes '...' never interpolate; double quotes "..." do.
  • -Force is needed to see hidden files with Get-ChildItem (and to remove read-only/system files with Remove-Item).
  • Comparisons use -eq/-gt/etc., not ==/> — those have different meanings in PowerShell (> is redirection).
  • $_ refers to the current pipeline object inside Where-Object / ForEach-Object blocks.
  • Arrays are @(), hashtables are @{} — easy to mix up when typing fast.
  • Get-ChildItem doesn't recurse by default; you need -Recurse explicitly.
  • Check $PSVersionTable.PSVersion before assuming a cmdlet/parameter exists — behavior differs between Windows PowerShell 5.1 and PowerShell 7+.

Further Reading