# Parameters: \`param()\`

A param() block at the top of a script names its inputs, so one script works on any folder; each parameter can have a type, a default value or be a \[switch\], Mandatory makes PowerShell ask for a missing one, and Tab completes their names.

Apprentice · PowerShell · Updated November 10, 2026

## After this lesson you can

- Give a script named parameters with param(), with types, default values and \[switch\]
- Make a parameter Mandatory, and run a script with its parameters by name, by position or with Tab completion

## Key takeaways

- param() at the top of a script names its inputs. .\Backup-Folder.ps1 -Path club puts club into $Path, and one script works on any folder.
- Values given without names fill the parameters in the order param() lists them. Names are clearer in anything you keep.
- A default value (= 'backup') is used when a parameter is left out. A type ([int]) turns away a value that doesn't fit before the script starts.
- A [switch] is on when you write it and off when you don't. [Parameter(Mandatory)] makes PowerShell ask for a value that's missing.
- Tab, Ctrl+Space and Get-Help know your script's parameters, the same as they know a cmdlet's.

Your homework deserves a backup, and a script can make one every evening. But a script with `homework` and `backup` typed into it only ever copies that one folder into that one place. For the chess club's sign-up sheet you'd copy the script and change the names, and next month you'd fix the same mistake in two files. PowerShell's own commands don't work that way: nobody edits `Copy-Item` to copy a different file. You hand it `-Path` and `-Destination`. Your scripts can take parameters too, and then one script works on any folder, the way an app opens any document you give it. Every script that other people run, from an IT team's setup script to a developer's build script, starts with its parameters.

Make this chapter's practice folder: some homework, a club's sign-up sheet and an empty backup folder. These lines are safe to run again:

```powershell
New-Item -ItemType Directory -Force -Path "$HOME\terminal-practice\smart-backup" | Out-Null
Set-Location "$HOME\terminal-practice\smart-backup"
New-Item -ItemType Directory -Force -Path homework, club, backup | Out-Null
Set-Content -Path homework\essay.txt -Value 'Why the Town Library Matters', 'First draft, two pages.'
Set-Content -Path homework\notes.txt -Value 'Chapter 4: read by Friday', 'Lab report due Monday'
Set-Content -Path homework\reading-list.txt -Value 'Hatchet', 'The Hobbit', 'A Wrinkle in Time'
New-Item -ItemType File -Force -Path homework\empty-draft.txt | Out-Null
Set-Content -Path club\sign-ups.txt -Value 'Ana', 'Ben', 'Chloe'
(Get-Item homework\essay.txt).LastWriteTime = (Get-Date).AddHours(-1)
(Get-Item homework\notes.txt).LastWriteTime = (Get-Date).AddDays(-3)
(Get-Item homework\reading-list.txt).LastWriteTime = (Get-Date).AddDays(-10)
(Get-Item club\sign-ups.txt).LastWriteTime = (Get-Date).AddDays(-20)
```

The last four lines set each file's date, as if you'd written the essay an hour ago, the notes three days ago, the reading list ten days ago and the sign-up sheet twenty days ago, so your results match the lesson's.

## A script's own inputs: param()

Open a new file with `code Backup-Folder.ps1` (*Writing Scripts in VS Code*), type these lines, and save. The name follows PowerShell's own rule, a verb and a noun (*Verb-Noun: Names That Explain Themselves*); `Backup` is one of the verbs on `Get-Verb`'s list.

```powershell
# Backup-Folder.ps1: copies the files in one folder into another.
param(
    $Path,
    $Destination
)
Get-ChildItem -Path $Path -File | Copy-Item -Destination $Destination
"Backed up $Path into $Destination."
```

`param( )` (read "param") is the script's list of inputs, its **param block**, and it comes first, after any comments. Each name in it is a **parameter**: you write it with a dash when you run the script, the same as a cmdlet's (*Parameters, Values and Switches*), and inside the script `$Path` holds whatever came after `-Path`. The last line, text on its own, is printed: the short way of writing `Write-Output`.

```powershell
.\Backup-Folder.ps1 -Path homework -Destination backup
Get-ChildItem backup -Name
.\Backup-Folder.ps1 homework backup
.\Backup-Folder.ps1 -Path club -Destination backup
```

```text
Backed up homework into backup.
empty-draft.txt
essay.txt
notes.txt
reading-list.txt
Backed up homework into backup.
Backed up club into backup.
```

The third line leaves the names out, so the values fill the parameters in the order `param()` lists them: they're **positional**. Names are clearer in anything you keep. The last line is the point: the same script, another folder, nothing edited.

## Defaults and types

Most evenings you'd type the same names, and copying every file every time wastes time on a big folder. Here's the script grown up. Replace everything in the file with this:

```powershell
# Backup-Folder.ps1: copies a folder's recent changes into a backup folder.
param(
    [string]$Path = 'homework',
    [string]$Destination = 'backup',
    [int]$Days = 1,
    [switch]$Preview
)
$since = (Get-Date).AddDays(-$Days)
$changed = Get-ChildItem -Path $Path -File | Where-Object LastWriteTime -gt $since
$changed | Copy-Item -Destination $Destination -WhatIf:$Preview
"Days looked back: $Days. Files copied: $($changed.Count)."
```

`= 'homework'` is a **default value**, used when you leave the parameter out. `[string]` and `[int]` in front are types (*Numbers, Dates and Types*). `$Days` decides how far back to look: only files changed since then pass `Where-Object` (*Filtering: Where-Object and Comparisons*).

```powershell
.\Backup-Folder.ps1
.\Backup-Folder.ps1 -Days 7
.\Backup-Folder.ps1 -Days seven
```

```text
Days looked back: 1. Files copied: 2.
Days looked back: 7. Files copied: 3.
Backup-Folder.ps1: Cannot process argument transformation on parameter 'Days'. Cannot convert value "seven" to type "System.Int32". Error: "The input string 'seven' was not in a correct format."
```

One day back finds the essay and the empty draft; seven days adds the notes. The type turned *seven* away before a single line of the script ran.

## On or off: \[switch\], and Mandatory

`[switch]$Preview` is a **switch parameter**: off unless you write `-Preview`, with no value after it, like `-Force`. `-WhatIf:$Preview` hands it on to `Copy-Item`, read "WhatIf, if Preview is on":

```powershell
.\Backup-Folder.ps1 -Preview
```

```text
What if: Performing the operation "Copy File" on target "Item: C:\Users\Sam\terminal-practice\smart-backup\homework\empty-draft.txt Destination: C:\Users\Sam\terminal-practice\smart-backup\backup\empty-draft.txt".
What if: Performing the operation "Copy File" on target "Item: C:\Users\Sam\terminal-practice\smart-backup\homework\essay.txt Destination: C:\Users\Sam\terminal-practice\smart-backup\backup\essay.txt".
Days looked back: 1. Files copied: 2.
```

Nothing was copied, yet the last line says two files were. The script can't tell the two cases apart yet; *If This, Then That: if, elseif and else* fixes that.

Some values have no sensible default. Put `[Parameter(Mandatory)]` (read "mandatory", meaning required) on the line above a parameter, and PowerShell asks for it when it's missing. For a moment, try it on `$Destination`, with its default taken away:

```powershell
    [Parameter(Mandatory)]
    [string]$Destination,
```

```text
cmdlet Backup-Folder.ps1 at command pipeline position 1
Supply values for the following parameters:
Destination: backup
Days looked back: 1. Files copied: 2.
```

`backup` is what was typed at the question. A parameter has a default or is Mandatory, not both, so put the default back afterwards: this chapter's script keeps it. Everything here works the same in Windows PowerShell 5.1; on a Mac or Linux, run the script as `./Backup-Folder.ps1`.

## Tab knows your parameters

Type `.\Backup-Folder.ps1 -` and press **Tab**:

```text
.\Backup-Folder.ps1 -Path
```

Press Tab again for `-Destination`, then `-Days` and `-Preview`, or **Ctrl+Space** to see all four at once (*Keyboard Shortcuts at the Prompt*). `Get-Help` knows them too:

```powershell
Get-Help .\Backup-Folder.ps1
```

```text
Backup-Folder.ps1 [[-Path] <string>] [[-Destination] <string>] [[-Days] <int>] [-Preview]
```

Square brackets mark what you may leave out, and `<int>` is the type. Your script now explains itself, like a cmdlet.

**Try it.** Preview a backup of the club folder that looks back 30 days, typing as few letters as you can with Tab. Then run it for real.

## Try it in the terminal

[Terminal Quest: Mission Control, goal 5](https://www.ask-codey.com/games/terminal-quest/mission-control/powershell/step): played right on the lesson page.

Your turn at Mission Control: the satellite needs a beacon. Write `beacon.ps1`, a one-line script whose `param($Callsign)` takes the call sign and outputs `BEACON` and the call sign, then pipe it into the transmitter. The goals before it are played for you.

## Check yourself

2 questions to try on the lesson page.

## So what

A param block turns a script with names typed into it into a tool that takes input like any command: defaults for the usual case, types that turn away nonsense, switches for choices, and Tab to fill it all in.

## Key terms

- [param Block](https://www.ask-codey.com/glossary/param-block)
- [Parameter](https://www.ask-codey.com/glossary/parameter-powershell)
- [Switch Parameter](https://www.ask-codey.com/glossary/switch-parameter)
- [Positional Parameter](https://www.ask-codey.com/glossary/positional-parameter)
- [Mandatory Parameter](https://www.ask-codey.com/glossary/mandatory-parameter)
- [Tab Completion](https://www.ask-codey.com/glossary/tab-completion-powershell)

## Cheat sheets

- [Parameters: \`param()\`](https://www.ask-codey.com/cheat-sheets/powershell-param-cheat-sheet)

## Related

- [Your First Script](https://www.ask-codey.com/lessons/powershell-your-first-script)
- [Parameters, Values and Switches](https://www.ask-codey.com/lessons/powershell-parameters)
- [Asking Questions: \`Read-Host\`](https://www.ask-codey.com/lessons/powershell-read-host)
- [If This, Then That: \`if\`, \`elseif\` and \`else\`](https://www.ask-codey.com/lessons/powershell-if-statements)
- [Exercise: The Smart Backup](https://www.ask-codey.com/lessons/exercise-powershell-the-smart-backup)

Source: https://www.ask-codey.com/lessons/powershell-param
