env.dev

PowerShell Cheat Sheet — Cmdlets, Pipeline & Objects

PowerShell 7 cmdlets, the object pipeline, filtering, environment variables, and execution policy — plus what differs from Windows PowerShell 5.1.

By env.dev Updated

PowerShell pipes objects, not text. That single difference is why ls | grep foo | awk {print $2} has no direct translation — you select a property instead of cutting a column, and nothing needs parsing. This reference covers PowerShell 7.6.5 (released 14 August 2026, the current LTS line), which runs on Windows, macOS, and Linux — not the Windows PowerShell 5.1 that ships in the box on Windows and is no longer getting features.

When to reach for this

  • You know the bash equivalent and need the cmdlet — filtering, sorting, and selecting fields off a command's output.
  • A script fails with running scripts is disabled on this system and you need the execution-policy fix.
  • You are setting environment variables on Windows and cannot remember which of $env:, setx, or [Environment]::SetEnvironmentVariable persists.

Which Version Are You Actually Running?

AspectWindows PowerShell 5.1PowerShell 7.x
Executablepowershell.exepwsh.exe / pwsh
Runtime.NET Framework 4.x.NET (cross-platform)
PlatformsWindows onlyWindows, macOS, Linux
StatusMaintenance — no new featuresActively developed
Installed by defaultYes, on WindowsNo — install separately

Check with $PSVersionTable.PSVersion. Both can be installed side by side, and they are separate shells with separate profiles and separate module paths — a module you installed in one will not be visible in the other. If a script only works in one of them, this is the first thing to check.

What Are the Core Cmdlets?

Cmdlets are Verb-Noun. Once you know the verbs — Get, Set, New, Remove, Start, Stop, Test — most names are guessable, and Get-Command *service* finds the rest.

CmdletDescriptionUnix equivalent
Get-ChildItemList directory contentsls
Set-LocationChange directorycd
Get-ContentRead a filecat
Set-ContentWrite a file, overwritingtee / >
Add-ContentAppend to a file>>
Copy-ItemCopy a file or directorycp
Move-ItemMove or renamemv
Remove-ItemDeleterm
New-ItemCreate a file or directorytouch / mkdir
Select-StringSearch text with regexgrep
Get-ProcessList running processesps
Stop-ProcessKill a processkill
Get-CommandFind a cmdlet or executablewhich / type
Get-HelpDocumentation for a cmdletman
Measure-ObjectCount, sum, average a propertywc

How Do You Filter and Shape the Pipeline?

CommandDescription
Where-Object { $_.Size -gt 1MB }Filter objects by a condition
Where-Object Name -like "*.log"Simplified syntax for a single comparison
Select-Object Name, LengthKeep only these properties
Select-Object -First 10Take the first ten objects
Select-Object -ExpandProperty NameUnwrap to the raw values, not objects
Sort-Object Length -DescendingSort by a property
Group-Object ExtensionGroup and count by a property
ForEach-Object { $_.ToUpper() }Run a block per object
Measure-Object Length -SumAggregate a numeric property
Get-MemberShow every property and method on an object

Get-Member is the one to internalise. Pipe anything into it and you get the full list of properties you can select or filter on — it replaces guessing at column positions entirely. The automatic variable $_ (or its clearer alias $PSItem) is the current pipeline object.

Comparison Operators

PowerShell does not use > and < for comparison — those are redirection. Operators are words prefixed with a hyphen, and they are case-insensitive by default.

OperatorMeaning
-eq / -neEqual / not equal
-gt / -geGreater than / greater or equal
-lt / -leLess than / less or equal
-like / -notlikeWildcard match (* and ?)
-match / -notmatchRegex match; sets $Matches
-contains / -inCollection membership
-ceq / -clike / -cmatchCase-sensitive variants
-and / -or / -notBoolean logic

How Do You Work With Environment Variables?

CommandScope
$env:PATHRead a variable in the current session
$env:API_KEY = "abc"Set for this session only — lost on close
Get-ChildItem Env:List every environment variable
Remove-Item Env:API_KEYUnset for this session
[Environment]::SetEnvironmentVariable("K","v","User")Persist for the current user
[Environment]::SetEnvironmentVariable("K","v","Machine")Persist system-wide; needs admin
setx K vPersist for the user; does not affect the current session

The trap is that setx and the [Environment] machine/user scopes write to the registry and only take effect in new processes — the shell you typed them in still has the old value. That is the single most common "I set it and it did not work" report on Windows. The Windows environment variables guide covers the session-versus-persistent split, the 1024-character setx truncation, and the GUI paths in full.

How Do You Fix "Running Scripts Is Disabled"?

A fresh Windows install refuses to run .ps1 files. The error is File ... cannot be loaded because running scripts is disabled on this system.

CommandEffect
Get-ExecutionPolicy -ListShow the policy at every scope
Set-ExecutionPolicy RemoteSigned -Scope CurrentUserThe usual fix — no admin needed
Set-ExecutionPolicy Bypass -Scope ProcessAllow everything for this session only
pwsh -ExecutionPolicy Bypass -File .\s.ps1Bypass for a single invocation
Unblock-File .\s.ps1Clear the mark-of-the-web on a downloaded script

RemoteSigned at CurrentUser scope is the right default: local scripts run, downloaded ones need a signature. Execution policy is not a security boundary — it stops accidents, not attackers, and Microsoft documents it as such.

What Are the Common Gotchas?

SymptomCauseFix
A variable set with setx is not visibleRegistry-scoped writes only apply to new processesSet $env:VAR too, or restart the shell
Output is truncated with a trailing ellipsisThe default table formatter drops columns that do not fitPipe to Format-List, or Select-Object the properties you need
A path with spaces failsThe argument was not quoted, or & is needed to invoke itUse & "C:\Program Files\app.exe"
Comparing to $null the wrong way round$x -eq $null on an array filters the array instead of testing itPut $null on the left: $null -eq $x
Redirect produces UTF-16 with a BOMWindows PowerShell 5.1 defaults to Unicode for >Use Set-Content -Encoding utf8, or move to PowerShell 7 where UTF-8 is the default
A function returns more than expectedEvery uncaptured expression is added to the outputAssign to $null or pipe to Out-Null to discard

For the Unix side of the same tasks, see the Bash scripting cheat sheet; if you are running containers on Windows, the Docker on Windows guide covers the WSL2 side.

Was this helpful?

Frequently Asked Questions

What is the difference between PowerShell and Windows PowerShell?

Windows PowerShell 5.1 (powershell.exe) runs on .NET Framework, is Windows-only, and is in maintenance with no new features. PowerShell 7.x (pwsh) runs on cross-platform .NET and is actively developed. They install side by side with separate profiles and module paths. Check with $PSVersionTable.PSVersion.

How do I fix "running scripts is disabled on this system"?

Run Set-ExecutionPolicy RemoteSigned -Scope CurrentUser, which needs no admin rights and lets local scripts run while requiring signatures on downloaded ones. For a single run, use pwsh -ExecutionPolicy Bypass -File script.ps1. Execution policy prevents accidents, not attackers.

Why does setx not change my environment variable in the current window?

setx and [Environment]::SetEnvironmentVariable with User or Machine scope write to the registry, and only processes started afterwards inherit the new value. The shell you typed the command in keeps its old copy. Set $env:VAR as well if you need it immediately.

What is $_ in PowerShell?

It is the current object in the pipeline, used inside Where-Object and ForEach-Object blocks. $PSItem is the identical, more readable alias. Pipe any object to Get-Member to see which properties you can reach through it.

Why is my PowerShell output cut off with an ellipsis?

The default table formatter drops columns that do not fit the console width rather than wrapping. Pipe to Format-List to see everything vertically, or use Select-Object to name only the properties you need.

Why should $null go on the left of a comparison?

When the right side is an array, -eq filters it and returns matching elements rather than a boolean, so if ($x -eq $null) behaves unexpectedly. Writing $null -eq $x forces a scalar comparison. This is the standard PSScriptAnalyzer recommendation.