PowerShell basics
PowerShell basics
PowerShell is Microsoft's shell and scripting language. It pipes .NET objects rather than text, which gives it a different grain from the bash family.
1. About PowerShell
PowerShell first shipped in 2006 as Windows PowerShell 1.0. It is a shell that runs on top of the .NET framework, where commands (cmdlets) take and emit objects rather than text. It came out of a system administration and automation lineage.
2. Two branches of PowerShell
| Item | Windows PowerShell 5.1 | PowerShell 7+ |
|---|---|---|
| Runtime | .NET Framework | .NET Core / .NET 5+ |
| Platform | Windows only | Windows · macOS · Linux |
| Default encoding | UTF-16 LE (BOM) | UTF-8 (no BOM) |
&& · ` |
` pipeline chain | |
Ternary ? : |
Not supported | Supported |
| Executable | powershell.exe |
pwsh |
| Support | Bundled with Windows; security patches only | Active development |
5.1 is shipped with Windows 10/11 and is not going away. 7+ requires a separate install (winget install Microsoft.PowerShell or brew install powershell on macOS).
3. cmdlet naming convention
cmdlets follow Verb-Noun.
| Verb | Meaning |
|---|---|
Get- |
Read (Get-Process, Get-ChildItem). |
Set- |
Modify (Set-Location, Set-Content). |
New- |
Create (New-Item, New-Object). |
Remove- |
Delete (Remove-Item). |
Start- · Stop- |
Start/stop. |
Invoke- |
Invoke (Invoke-WebRequest, Invoke-RestMethod). |
The approved verb list comes from Get-Verb. Consistent naming helps autocomplete and learning.
4. Aliases
| Alias | Real name |
|---|---|
ls · dir · gci |
Get-ChildItem |
cd · sl |
Set-Location |
cat · gc |
Get-Content |
cp · copy |
Copy-Item |
mv · move |
Move-Item |
rm · del |
Remove-Item |
pwd |
Get-Location |
cls |
Clear-Host |
Inside scripts the real name is preferred for readability (PSScriptAnalyzer's AvoidUsingCmdletAliases).
5. .ps1 and execution policy
.ps1 is the PowerShell script extension. For safety the default execution policy is Restricted, so a freshly downloaded script will not run right away.
| Policy | Behavior |
|---|---|
Restricted |
Blocked (default). |
AllSigned |
Only signed scripts. |
RemoteSigned |
Scripts from the internet need a signature, local scripts run freely. |
Unrestricted |
Internet scripts run after a warning. |
Bypass |
Everything passes (CI, etc.). |
Get-ExecutionPolicy
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
-Scope CurrentUser applies only to the current user, no admin rights needed.
6. Object pipes
Where bash pipes carry text, PowerShell pipes carry objects:
# bash
ps -ef | grep node | awk '{print $2}'
# PowerShell
Get-Process | Where-Object { $_.Name -eq "node" } | Select-Object -ExpandProperty Id
PowerShell accesses object properties directly, so awk-style text parsing is unnecessary. On the other hand, output from external commands (git, curl) arrives as strings, so text parsing comes back into play there.
7. bash equivalents
| Task | bash | PowerShell |
|---|---|---|
| Directory listing | ls -la |
Get-ChildItem -Force |
| Current location | pwd |
Get-Location (pwd) |
| Clear screen | clear |
Clear-Host (cls) |
| View file | cat file |
Get-Content file |
| Find file | find . -name "*.md" |
Get-ChildItem -Recurse -Filter *.md |
| Search content | grep -r "TODO" . |
Select-String -Path *.* -Pattern "TODO" |
| Read env var | echo $PATH |
$env:PATH |
| Set env var | export FOO=bar |
$env:FOO = "bar" |
| HTTP request | curl ... |
Invoke-WebRequest ... |
| Chain on success | a && b |
a; if ($?) { b } (5.1) / a && b (7+) |
| Exit code | $? |
$LASTEXITCODE (external exe) / $? (cmdlet) |
8. Encoding traps (5.1)
Windows PowerShell 5.1 defaults Out-File, Set-Content, and > redirection to UTF-16 LE (with BOM). When other tools expect UTF-8 the resulting file is broken.
# Safe pattern under 5.1
"hello" | Out-File -Encoding utf8 file.txt
Set-Content -Encoding utf8 -Path file.txt -Value "hello"
PowerShell 7+ defaults to UTF-8 (no BOM).
9. Basic syntax
$name = "world"
Write-Output "hello, $name"
if (Test-Path "config.json") {
Write-Output "found"
} else {
Write-Output "missing"
}
foreach ($f in Get-ChildItem -Filter *.txt) {
Write-Output $f.Name
}
function Greet {
param([string]$Name)
"hello, $Name"
}
Greet -Name "alice"
10. Common pitfalls
5.1 has no && / || — chains have to be unrolled into ; if ($?) { ... }.
Redirecting an external exe's stderr with 2>&1 under 5.1 wraps it in an ErrorRecord, so $? becomes $false. Leave stderr alone where possible.
Carelessly applying Set-ExecutionPolicy Bypass -Scope Process system-wide — restrict it with -Scope Process or -Scope CurrentUser.
Output stays in UTF-16 LE so other tools (Node, Python) cannot read it — pass -Encoding utf8 explicitly.
cmdlet names are case-insensitive and feel familiar, but relying on aliases when piping output to external tools can produce subtle compatibility issues.
Closing thoughts
Object pipes, Verb-Noun naming, and the strong cmdlet library are PowerShell's draws. The 5.1-era encoding, missing &&, and execution policy form the initial learning cost. The fact that 7+ is cross-platform and stands next to bash points at the future shape.
Next
- cmd-and-bat
- cross-platform-scripts
Microsoft PowerShell docs · about_Execution_Policies · about_Pipelines · PowerShell on GitHub · PSScriptAnalyzer for reference.