PowerShell Cheat Sheet

Sidebar

Programming · PowerShell Cheat Sheet

Everyday PowerShell for Windows: finding help, editing the command line, files, the object pipeline, variables and operators, scripts and the execution policy, web requests and system tasks. Written for Windows PowerShell 5.1, the version installed on this machine (PowerShell 7 is not installed); features that need PowerShell 7 are marked. Every command and parameter on the sheet was checked to exist in this installation.

Help & Discovery

$PSVersionTable.PSVersionWhich PowerShell you are in (this machine: Windows PowerShell 5.1)
Get-Help Get-Process -ExamplesShow examples; also -Full, -Detailed, -Online, -ShowWindow
Update-HelpDownload the full help files (run PowerShell as administrator)
Get-Command *service*Find commands by part of a name
Get-Command Stop-Service -SyntaxShow every way to call a command
Get-VerbThe approved verbs: commands are named Verb-Noun
Get-MemberPipe any object to it to list its properties and methods
Get-Alias / Get-Alias -Definition Get-ChildItemList aliases / find the aliases of a command
Show-Command Get-ProcessA small window for filling in a command's options
TabCompletes commands, parameters, paths and even parameter values

Command-Line Keys (PSReadLine 2.0.0 here)

Up / DownPrevious / next command in the history
Ctrl+R / Ctrl+SSearch the history backwards / forwards as you type
F7A pop-up list of the history, a classic Windows console feature; it may behave differently inside Windows Terminal
Tab / Shift+TabComplete forwards / backwards
Ctrl+SpaceA menu of every possible completion
Alt+.Insert the last argument of the previous command
Ctrl+W or Ctrl+BackspaceDelete the word before the cursor
Ctrl+Left / Ctrl+RightMove one word
Ctrl+Z / Ctrl+YUndo / redo while editing the line
Shift+EnterStart a new line without running
Ctrl+LClear the screen
Ctrl+CCopy if text is selected, otherwise cancel the current line or command
Ctrl+Alt+?Show every key binding
Get-PSReadLineOptionSee the current editing settings; predictions arrive with PSReadLine 2.1 or later (PowerShell 7)

Moving Around & Working with Files

Set-Location D:\Work (cd)Change folder; Get-Location (pwd) shows where you are
Push-Location / Pop-LocationRemember the current folder and go back to it later
Get-ChildItem -Recurse -File -Filter *.md (ls, dir)List files; -Directory, -Hidden, -Force, -Name, -Depth 2 help
New-Item notes.txt -ItemType FileCreate a file; -ItemType Directory for a folder
Copy-Item a.txt b.txt Move-Item Rename-ItemCopy, move and rename; -Recurse for folders
Remove-Item old -Recurse -ForceDelete (no recycle bin). Add -WhatIf first to see what would happen
Test-Path .\file.txtTrue or False: does it exist?
Get-Content log.txt -Tail 20 -WaitShow the end of a file and keep following it; -Raw reads it as one string
Set-Content / Add-Content / Out-FileWrite text to a file / append / write command output
Join-Path A B Split-Path Resolve-PathBuild, take apart and resolve paths
Compress-Archive -Path src -DestinationPath out.zipMake a zip; Expand-Archive unzips it
Get-FileHash file.isoA checksum (SHA256 by default)
Select-String -Path *.md -Pattern 'TODO'Search inside files (sls); there is no -Recurse, so pipe from Get-ChildItem -Recurse

The Pipeline

Get-Process | Sort-Object CPU -Descending | Select-Object -First 5Each command passes objects, not text, to the next
Where-Object { $_.Length -gt 1MB }Keep matching items (where, ?); $_ is the current item. Short form: Where-Object Length -gt 1MB
Select-Object Name, LengthChoose properties; -First, -Last, -Unique, -ExpandProperty
Sort-Object Length -DescendingSort (sort)
Group-Object ExtensionCount items per value
Measure-Object Length -Sum -Average -MaximumTotals and averages; with no property it counts
ForEach-Object { $_.Name.ToUpper() }Run code on each item (%)
Select-Object @{Name='MB'; Expression={$_.Length/1MB}}A calculated property
Format-Table -AutoSize / Format-List *Display as a table / as a list of every property (ft, fl)
Out-GridViewA sortable, filterable window of the results
Tee-Object -FilePath out.txtShow the output and also save it
Compare-Object $a $bDifferences between two collections
Filter earlyUse a command's own -Filter or -Name parameter before Where-Object: it is much faster on big folders

Variables, Types & Operators

$name = 'Philip'Variables start with $; no declaration needed
[int]$n = '42'Force a type; others: [string], [datetime], [bool], [double]
$env:PATH $HOME $PWD $PROFILEEnvironment variable / home / current folder / profile path
$? $LASTEXITCODEDid the last command succeed? / exit code of the last program
$null $true $falseBuilt-in values
-eq -ne -gt -ge -lt -leCompare. Text comparison ignores case unless you use -ceq
-like 'a*' -match '^a.+z$'Wildcard / regular expression match; -notlike, -notmatch
-contains -inIs the item in the list? ($list -contains 3 or 3 -in $list)
-and -or -not -xor !Logic. In Windows PowerShell 5.1 there is no && or || between commands
-replace -split -join -fText operators: 'a,b' -split ',', $a -join ';', '{0:N2}' -f 3.14159
1..5A range of numbers
'single $x' "double $x" "$($o.Name)"Single quotes are literal; double quotes expand variables; $( ) inside them runs an expression
@' … '@ @" … "@Here-strings for several lines (the closing mark must start a line)
` (backtick)The escape character, and a line continuation at the end of a line

Arrays, Hashtables & Objects

$a = @(1,2,3); $a[0]; $a[-1]; $a.CountArrays are zero-based; -1 is the last item
$a += 4Adds an item by building a new array, so avoid it in big loops
$h = @{ name='x'; age=5 }Hashtable; read with $h.name or $h['name']; $h.Keys, $h.Values
[ordered]@{ a=1; b=2 }Keeps the order you wrote
[pscustomobject]@{ Name='x'; Size=3 }Make an object with properties
Invoke-Thing @paramsSplatting: pass a hashtable of parameters with @
'a b c'.Split(' ') .Trim() .Replace('a','b')String methods; also .ToUpper(), .Substring(2,3), .Contains('x')
Import-Csv f.csv / Export-Csv f.csv -NoTypeInformationRead / write CSV as objects
Get-Content f.json -Raw | ConvertFrom-JsonTurn JSON into objects
$obj | ConvertTo-Json -Depth 5Turn objects into JSON; the default -Depth 2 silently cuts deeper levels

Control Flow, Functions & Errors

if ($x -gt 1) { } elseif ($x -eq 1) { } else { }Conditions
switch ($x) { 1 { 'one' } default { 'other' } }Multi-way choice; switch -Wildcard and -Regex also work
foreach ($f in $files) { } for while do { } until ()Loops; break and continue work as usual
function Get-Thing { param([string]$Path, [switch]$Force) … }A function with typed parameters; add [CmdletBinding()] before param for -Verbose and -WhatIf
return $x / Write-Output $xAnything a function outputs is returned; Write-Host only prints to the screen
try { } catch { $_.Exception.Message } finally { }Handle errors. catch only sees terminating errors
-ErrorAction StopMake a command's errors terminating so try/catch catches them
$ErrorActionPreference = 'Stop'Stop on any error for the whole script (the default is Continue)
$Error[0]The most recent error
throw 'message'Raise your own error
Write-Verbose Write-Warning Write-ErrorMessages of different levels
Measure-Command { … }Time a block of code
. .\lib.ps1Dot-sourcing: run a script in the current scope so its functions stay available

Scripts, Execution Policy & Your Profile

.\script.ps1Run a script in the current folder (the .\ is required)
Get-ExecutionPolicy -ListShow the policy at each scope. Here: LocalMachine Unrestricted, CurrentUser undefined
Set-ExecutionPolicy RemoteSigned -Scope CurrentUserAllow your own scripts for your account only (see the Python Environments sheet for the venv error)
Unblock-File .\downloaded.ps1Remove the 'downloaded from the internet' mark so a script may run
powershell -NoProfile -ExecutionPolicy Bypass -File x.ps1Run one script ignoring the policy for that run only: the pattern your .cmd launchers use
$PROFILEPath of your profile script: here C:\Users\emuba\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
Test-Path $PROFILEDoes it exist yet?
New-Item -Path $PROFILE -ItemType File -ForceCreate it; then put aliases, functions and prompt tweaks in it
Set-Alias gs Get-StatusA session alias; put it in your profile to keep it
Start-Transcript -Path log.txtRecord everything typed and shown; Stop-Transcript ends it

Web, JSON & APIs

Invoke-RestMethod https://api.example.com/itemsGET and parse JSON automatically (irm)
Invoke-WebRequest $url -OutFile f.zipDownload a file; the result also has .StatusCode, .Content, .Headers (iwr)
-Method Post -Body ($o | ConvertTo-Json) -ContentType 'application/json'Send JSON
-Headers @{ Authorization = "Bearer $token" }Add headers
-UseBasicParsingSkip the Internet Explorer engine in Windows PowerShell 5.1 (avoids a setup prompt on some machines)
curl and wgetIn Windows PowerShell 5.1 these are aliases of Invoke-WebRequest, not the real programs. Type curl.exe to run the real curl
Test-NetConnection localhost -Port 8000Can I reach that port? (handy for checking your FastAPI server)
Resolve-DnsName example.comDNS lookup
Test-Connection example.comPing
PowerShell 7 onlyInvoke-RestMethod -SkipHttpErrorCheck and some other parameters do not exist in 5.1

Processes, Services, Network & Windows

Get-Process chrome | Stop-ProcessFind and stop a program (ps, kill)
Start-Process notepad -Verb RunAsStart a program, here as administrator
Get-Service / Start-Service / Stop-Service / Restart-ServiceManage Windows services
Get-NetTCPConnection -State ListenWhich ports are being listened on (and by which process id)
Get-NetIPAddressYour IP addresses
Get-CimInstance Win32_OperatingSystemSystem details; Get-ComputerInfo gives many more
Get-WinEvent -LogName System -MaxEvents 20Read the Windows event log
Get-ChildItem Env:List environment variables
[Environment]::SetEnvironmentVariable('X','v','User')Set a permanent variable for your account (new windows only)
Get-ItemProperty HKCU:\Software\…Read the registry like a folder; Set-ItemProperty changes it
Get-Clipboard / Set-ClipboardRead / write the clipboard
Get-Date -Format 'yyyy-MM-dd'Formatted date
Start-Sleep -Seconds 5Wait
Start-Job { … } / Get-Job / Receive-JobRun code in the background and collect the result
Get-ScheduledTask / Register-ScheduledTaskWork with Task Scheduler

Modules & Remoting

Get-Module -ListAvailableModules installed
Import-Module NameLoad one (most load automatically when you use their commands)
Find-Module name / Install-Module name -Scope CurrentUserSearch the PowerShell Gallery and install without administrator rights
Get-InstalledModuleModules installed from the Gallery
Enter-PSSession -ComputerName pcInteractive session on another Windows computer (needs remoting set up)
Invoke-Command -ComputerName pc { … }Run code remotely
Linux and WSLUse ssh or wsl from PowerShell; PowerShell 7 can also remote over SSH

Windows PowerShell 5.1 vs PowerShell 7

powershell.exe / pwsh.exe5.1 ships with Windows (installed here); 7 is a separate download and installs beside it. 7 (pwsh) is not installed on this machine
Get itwinget install Microsoft.PowerShell (winget is available here; the package id is from my knowledge)
&& and ||Run the next command only if the last one succeeded / failed: 7 only
? : and ?? ?.Ternary, null-coalescing and null-conditional operators: 7 only
ForEach-Object -Parallel7 only (the parameter does not exist here)
Encoding5.1 writes UTF-16 with > and Out-File; 7 writes UTF-8 without a BOM (see the tip below)
Predictions and coloursInline command prediction and the $PSStyle colour object are 7 features

A Reasonable Starter Profile (my suggestions)

Set-Alias ll Get-ChildItemA short name for listing
function mkcd($p){ New-Item $p -ItemType Directory -Force | Out-Null; Set-Location $p }Make a folder and go into it
function which($n){ (Get-Command $n).Source }Where is this program?
$PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'Every Out-File writes UTF-8 (5.1 adds a BOM)
$env:PATH += ';C:\tools'Add a folder to PATH for the session
Set-PSReadLineOption -EditMode WindowsThe default editing keys, stated explicitly
Why does my redirected file look like garbage? Encoding
In Windows PowerShell 5.1, command > file.txt and Out-File write UTF-16 (with a byte-order mark), which many tools show as text with gaps between the letters. Use command | Out-File file.txt -Encoding utf8 instead (utf8 in 5.1 adds a BOM) or Set-Content -Encoding UTF8. PowerShell 7 writes plain UTF-8 by default.
Safe habits for deleting and changing things
Put -WhatIf after Remove-Item, Move-Item, Stop-Process and similar commands to see what would happen, and -Confirm to be asked about each one. Remove-Item does not use the recycle bin, and Remove-Item -Recurse -Force on the wrong folder cannot be undone. Test a Get-ChildItem with the same path first.
"Running scripts is disabled on this system"
That is the execution policy, not a bug. The one-line fix for your own account is Set-ExecutionPolicy RemoteSigned -Scope CurrentUser, as explained on the Python Environments sheet. Your launchers use -ExecutionPolicy Bypass for a single run, which changes nothing permanently.