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, -ShowWindowUpdate-HelpDownload the full help files (run PowerShell as administrator)Get-Command *service*Find commands by part of a nameGet-Command Stop-Service -SyntaxShow every way to call a commandGet-VerbThe approved verbs: commands are named Verb-NounGet-MemberPipe any object to it to list its properties and methodsGet-Alias / Get-Alias -Definition Get-ChildItemList aliases / find the aliases of a commandShow-Command Get-ProcessA small window for filling in a command's optionsTabCompletes commands, parameters, paths and even parameter valuesCommand-Line Keys (PSReadLine 2.0.0 here)
Up / DownPrevious / next command in the historyCtrl+R / Ctrl+SSearch the history backwards / forwards as you typeF7A pop-up list of the history, a classic Windows console feature; it may behave differently inside Windows TerminalTab / Shift+TabComplete forwards / backwardsCtrl+SpaceA menu of every possible completionAlt+.Insert the last argument of the previous commandCtrl+W or Ctrl+BackspaceDelete the word before the cursorCtrl+Left / Ctrl+RightMove one wordCtrl+Z / Ctrl+YUndo / redo while editing the lineShift+EnterStart a new line without runningCtrl+LClear the screenCtrl+CCopy if text is selected, otherwise cancel the current line or commandCtrl+Alt+?Show every key bindingGet-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 arePush-Location / Pop-LocationRemember the current folder and go back to it laterGet-ChildItem -Recurse -File -Filter *.md (ls, dir)List files; -Directory, -Hidden, -Force, -Name, -Depth 2 helpNew-Item notes.txt -ItemType FileCreate a file; -ItemType Directory for a folderCopy-Item a.txt b.txt Move-Item Rename-ItemCopy, move and rename; -Recurse for foldersRemove-Item old -Recurse -ForceDelete (no recycle bin). Add -WhatIf first to see what would happenTest-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 stringSet-Content / Add-Content / Out-FileWrite text to a file / append / write command outputJoin-Path A B Split-Path Resolve-PathBuild, take apart and resolve pathsCompress-Archive -Path src -DestinationPath out.zipMake a zip; Expand-Archive unzips itGet-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 -RecurseThe Pipeline
Get-Process | Sort-Object CPU -Descending | Select-Object -First 5Each command passes objects, not text, to the nextWhere-Object { $_.Length -gt 1MB }Keep matching items (where, ?); $_ is the current item. Short form: Where-Object Length -gt 1MBSelect-Object Name, LengthChoose properties; -First, -Last, -Unique, -ExpandPropertySort-Object Length -DescendingSort (sort)Group-Object ExtensionCount items per valueMeasure-Object Length -Sum -Average -MaximumTotals and averages; with no property it countsForEach-Object { $_.Name.ToUpper() }Run code on each item (%)Select-Object @{Name='MB'; Expression={$_.Length/1MB}}A calculated propertyFormat-Table -AutoSize / Format-List *Display as a table / as a list of every property (ft, fl)Out-GridViewA sortable, filterable window of the resultsTee-Object -FilePath out.txtShow the output and also save itCompare-Object $a $bDifferences between two collectionsFilter earlyUse a command's own -Filter or -Name parameter before Where-Object: it is much faster on big foldersVariables, 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.141591..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 lineArrays, 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 propertiesInvoke-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 objectsGet-Content f.json -Raw | ConvertFrom-JsonTurn JSON into objects$obj | ConvertTo-Json -Depth 5Turn objects into JSON; the default -Depth 2 silently cuts deeper levelsControl Flow, Functions & Errors
if ($x -gt 1) { } elseif ($x -eq 1) { } else { }Conditionsswitch ($x) { 1 { 'one' } default { 'other' } }Multi-way choice; switch -Wildcard and -Regex also workforeach ($f in $files) { } for while do { } until ()Loops; break and continue work as usualfunction Get-Thing { param([string]$Path, [switch]$Force) … }A function with typed parameters; add [CmdletBinding()] before param for -Verbose and -WhatIfreturn $x / Write-Output $xAnything a function outputs is returned; Write-Host only prints to the screentry { } 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 errorthrow 'message'Raise your own errorWrite-Verbose Write-Warning Write-ErrorMessages of different levelsMeasure-Command { … }Time a block of code. .\lib.ps1Dot-sourcing: run a script in the current scope so its functions stay availableScripts, 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 undefinedSet-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 runpowershell -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.ps1Test-Path $PROFILEDoes it exist yet?New-Item -Path $PROFILE -ItemType File -ForceCreate it; then put aliases, functions and prompt tweaks in itSet-Alias gs Get-StatusA session alias; put it in your profile to keep itStart-Transcript -Path log.txtRecord everything typed and shown; Stop-Transcript ends itWeb, 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 curlTest-NetConnection localhost -Port 8000Can I reach that port? (handy for checking your FastAPI server)Resolve-DnsName example.comDNS lookupTest-Connection example.comPingPowerShell 7 onlyInvoke-RestMethod -SkipHttpErrorCheck and some other parameters do not exist in 5.1Processes, Services, Network & Windows
Get-Process chrome | Stop-ProcessFind and stop a program (ps, kill)Start-Process notepad -Verb RunAsStart a program, here as administratorGet-Service / Start-Service / Stop-Service / Restart-ServiceManage Windows servicesGet-NetTCPConnection -State ListenWhich ports are being listened on (and by which process id)Get-NetIPAddressYour IP addressesGet-CimInstance Win32_OperatingSystemSystem details; Get-ComputerInfo gives many moreGet-WinEvent -LogName System -MaxEvents 20Read the Windows event logGet-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 itGet-Clipboard / Set-ClipboardRead / write the clipboardGet-Date -Format 'yyyy-MM-dd'Formatted dateStart-Sleep -Seconds 5WaitStart-Job { … } / Get-Job / Receive-JobRun code in the background and collect the resultGet-ScheduledTask / Register-ScheduledTaskWork with Task SchedulerModules & Remoting
Get-Module -ListAvailableModules installedImport-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 rightsGet-InstalledModuleModules installed from the GalleryEnter-PSSession -ComputerName pcInteractive session on another Windows computer (needs remoting set up)Invoke-Command -ComputerName pc { … }Run code remotelyLinux and WSLUse ssh or wsl from PowerShell; PowerShell 7 can also remote over SSHWindows 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 machineGet 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 onlyForEach-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 featuresA Reasonable Starter Profile (my suggestions)
Set-Alias ll Get-ChildItemA short name for listingfunction mkcd($p){ New-Item $p -ItemType Directory -Force | Out-Null; Set-Location $p }Make a folder and go into itfunction 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 sessionSet-PSReadLineOption -EditMode WindowsThe default editing keys, stated explicitlyWhy 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.