PowerShell 7 is cross-platform, ships with a real package manager, and treats everything as objects rather than text. If you write more than two lines of bash or a single .bat file in a typical week, learning to lean on PowerShell pays back quickly. Here's a starter kit of scripts and patterns we use ourselves.
Install it (the modern way)
On Windows 11 or Server 2022, install via winget:
winget install --id Microsoft.PowerShell --source winget
On macOS or Linux, use the official packages or
dotnet tool install --global PowerShell. Then launch pwsh.
Note: this is a different binary from the legacy powershell.exe shipped
with Windows. The new one is what you want.
Your profile is your shell config
Find your profile with $PROFILE. Anything you write there runs at
shell startup. A useful starting set:
# Better tab completion
Set-PSReadLineOption -PredictionSource HistoryAndPlugin
Set-PSReadLineKeyHandler -Key Tab -Function MenuComplete
# Aliases that don't fight muscle memory
Set-Alias ll Get-ChildItem
function g { git $args }
function .. { Set-Location .. }
# Prompt with current branch
function prompt {
$branch = (git branch --show-current 2>$null)
$b = if ($branch) { " ($branch)" } else { "" }
"$($PWD.Path)$b> "
}
A real script: provision a new .NET project
Most of our team's productivity scripts follow the same shape: parameters at the
top, a few Write-Host updates, and external commands invoked
directly. Here's a script that scaffolds an ASP.NET Core API with a test project
and a Git repo, ready to commit:
param(
[Parameter(Mandatory)] [string]$Name,
[string]$Path = (Get-Location).Path
)
$ErrorActionPreference = 'Stop'
$root = Join-Path $Path $Name
New-Item -ItemType Directory $root | Out-Null
Push-Location $root
try {
dotnet new sln -n $Name
dotnet new webapi -n "$Name.Api" -o "src/$Name.Api"
dotnet new xunit -n "$Name.Tests" -o "tests/$Name.Tests"
dotnet sln add (Get-ChildItem -Recurse -Filter *.csproj)
git init -q
"bin/", "obj/", ".vs/" | Set-Content .gitignore
git add . ; git commit -qm "Initial scaffold"
Write-Host "Created $Name at $root" -ForegroundColor Green
} finally {
Pop-Location
}
Save it as New-DotnetProject.ps1, drop it on your $PATH,
and a new project is one command away.
Objects, not strings
The shift in mindset that unlocks PowerShell is treating commands as object pipelines, not text streams. Compare:
# Get the top 5 largest files in this folder tree
Get-ChildItem -Recurse -File `
| Sort-Object Length -Descending `
| Select-Object -First 5 Name, Length, FullName
No awk, no parsing. The cmdlet returns rich objects; you sort, filter,
and project them with named properties.
Wrangling Git
A handful of one-liners that earn their keep:
# Delete every local branch already merged into main
git branch --merged main `
| Where-Object { $_ -notmatch '^\*|main|develop' } `
| ForEach-Object { git branch -d $_.Trim() }
# Find PRs you authored that touched a file
git log --author="$(git config user.email)" -- src/Auth.cs `
| Select-String '^commit' -SimpleMatch:$false
Modules worth knowing
- PSReadLine — already installed; turn on history-based prediction.
- Pester — test framework, perfect for testing your scripts.
- posh-git — branch and status info baked into your prompt.
- Az — the official Azure module; first-class for cloud workflows.
Get-Help Get-ChildItem -Examples for any
cmdlet. The built-in help is genuinely good; you rarely need to leave the shell.
Where to go from here
Pick one tedious thing in your workflow — provisioning a project, deploying to a staging slot, generating a release note — and write a script for it this week. Iterate on it. Within a month you'll have a small library of scripts that quietly save you an hour a day.
We run a "scripting your dev loop" workshop as part of our coaching program. If you'd like a curated reading list and a few exercises, drop us a line.