Scripts, execution policy and profiles

PowerShell · Practical · 10 min

Saving work as scripts is how ad-hoc commands become repeatable automation.

A script is a .ps1 file. It can start with a param() block, exactly like a function, so it gets named parameters, validation and tab completion. Run it with its path, ./backup.ps1 -Source ./docs, or from another shell with pwsh -File ./backup.ps1. On Linux and macOS a #!/usr/bin/env pwsh shebang plus chmod +x also works.

Useful automatic variables: $PSScriptRoot is the folder containing the script, the reliable base for relative paths; $PSCommandPath is the script's full path. #Requires -Version 7.0 or #Requires -Modules Name stop the script early if requirements are missing. Set-StrictMode -Version Latest turns references to undefined variables and properties into errors.

Execution policy applies on Windows only: it controls whether scripts may run (Restricted, RemoteSigned, AllSigned, Unrestricted, Bypass). Check it with Get-ExecutionPolicy -List; developers typically use Set-ExecutionPolicy -Scope CurrentUser RemoteSigned. Downloaded files are marked and may need Unblock-File. It is a safety feature against accidents, not a security boundary.

Dot-sourcing . ./helpers.ps1 runs a script in the current scope so its functions and variables remain available. Your profile, at the path in $PROFILE, is dot-sourced at startup; put aliases, functions and prompt tweaks there.

Example

# file: backup.ps1
#Requires -Version 7.0
param(
  [Parameter(Mandatory)][string]$Source,
  [string]$Destination = (Join-Path $PSScriptRoot 'backups')
)
Set-StrictMode -Version Latest
New-Item -ItemType Directory -Path $Destination -Force | Out-Null
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
Compress-Archive -Path $Source -DestinationPath "$Destination/backup-$stamp.zip"
"Saved to $Destination"
# Running it:
#   ./backup.ps1 -Source ./docs
#   pwsh -File ./backup.ps1 -Source ./docs      (from bash, cmd, cron...)
# Windows only:
#   Get-ExecutionPolicy -List
#   Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
# . ./helpers.ps1    # dot-source: load its functions into this scope
# $PROFILE           # path of your startup profile script

Remember

  • A param() block at the top makes a script take named parameters
  • $PSScriptRoot anchors relative paths
  • Execution policy is a Windows safety setting, not security; dot-source to import

Watch out for

  • Using relative paths that depend on the caller's current directory instead of $PSScriptRoot.

Check yourself

  1. A script reads './config.json' and fails when run from another folder. What is the fix?
  2. What does dot-sourcing `. ./lib.ps1` do?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies