# Functions: Naming a Job

A function you share gets a cmdlet's kind of name, an approved verb from Get-Verb and a singular noun, takes its inputs in param() and outputs objects rather than sentences, so its results can be sorted, filtered and saved; a file of functions is loaded into your session with a dot.

Journeyman · PowerShell · Updated November 10, 2026

## After this lesson you can

- Write a function with an approved verb-noun name and a param() block, and load a file of functions with a dot
- Return objects from a function instead of text, so its output can be sorted, filtered and saved

## Key takeaways

- Name a tool like a cmdlet: an approved verb from Get-Verb, a dash, and a singular noun, such as Get-Song.
- param() gives a function named parameters, with types and default values, the same as a script's.
- Output objects, not sentences. The next command can sort, filter, count and save objects, but text has no properties to work with.
- Running a file of functions forgets them when it ends. A dot and a space in front, . .\PlaylistTools.ps1, loads them into your session.

You keep your road-trip playlist in a spreadsheet: each song, who plays it, how many minutes it lasts and its mood. Before every drive you ask it the same questions. Which songs are chill? What fits in a 20-minute run to the store? Can I drop the one I'm tired of? You could type a long pipeline each time, or you could build a few tools that answer by name, like `Get-Song -Mood Chill`. That's what IT teams and developers do with the jobs they repeat: they write functions that look and behave like PowerShell's own commands, so anyone can guess how to use them. This chapter builds those playlist tools, one feature at a time.

Make the practice folder, with the playlist as a CSV file (*Spreadsheets as Objects: `Import-Csv`*). These lines are safe to run again, and they put the playlist back to these seven songs whenever you want a fresh start:

```powershell
New-Item -ItemType Directory -Force -Path "$HOME\terminal-practice\playlist-tools" | Out-Null
Set-Location "$HOME\terminal-practice\playlist-tools"
Set-Content road-trip.csv @'
Title,Artist,Minutes,Mood
Mile Marker 9,Juniper Kite,4,Upbeat
Gas Station Coffee,The Night Owls,3,Upbeat
Rainy Overpass,Juniper Kite,6,Chill
Backseat Snacks,Maple Street,3,Upbeat
Cruise Control,The Night Owls,5,Chill
Left at the Lighthouse,Maple Street,7,Focus
Last Exit Home,Juniper Kite,4,Chill
'@
```

They print nothing when they work.

## A name from Get-Verb's list

In *Aliases and Small Functions* you made `mkcd`, a short name for your own use. A tool that other people use deserves a name like a cmdlet's: a verb, a dash and a noun (*Verb-Noun: Names That Explain Themselves*). The noun is the thing the tool works on, and it's singular even when there are many: `Get-Song`, not `Get-Songs`, the same as `Get-ChildItem`. The verb comes from PowerShell's list of **approved verbs**, which `Get-Verb` shows. Ask it about the verbs this chapter uses:

```powershell
Get-Verb -Verb Get, Add, Remove, Show, Limit
```

```text
Verb   AliasPrefix Group  Description
----   ----------- -----  -----------
Add    a           Common Adds a resource to a container, or attaches an item to another item
Get    g           Common Specifies an action that retrieves a resource
Remove r           Common Deletes a resource from a container
Show   sh          Common Makes a resource visible to the user
Limit  l           Data   Applies constraints to a resource
```

Each verb means the same thing all over PowerShell: `Get` only reads and never changes anything, and `Remove` takes something away. Try `Get-Verb -Verb Play, Shuffle, Delete`: it prints nothing, because none of the three is on the list (the job of *Delete* belongs to `Remove`). When you turn your tools into a module in *Your Own Module*, PowerShell warns about names whose verbs aren't on the list, so choose from it now. In Windows PowerShell 5.1, Get-Verb shows only the Verb and Group columns.

## Text, or objects?

Here's a first try at a playlist tool, with an approved name. Type it at the prompt (Enter after an open brace starts a new line), then run it:

```powershell
function Show-Song {
    param($Mood)
    foreach ($song in Import-Csv road-trip.csv) {
        if ($song.Mood -eq $Mood) {
            "$($song.Title) by $($song.Artist), $($song.Minutes) min"
        }
    }
}
Show-Song -Mood Chill
```

```text
Rainy Overpass by Juniper Kite, 6 min
Cruise Control by The Night Owls, 5 min
Last Exit Home by Juniper Kite, 4 min
```

It reads nicely. Now ask for the shortest song first:

```powershell
Show-Song -Mood Chill | Sort-Object Minutes
```

```text
Rainy Overpass by Juniper Kite, 6 min
Cruise Control by The Night Owls, 5 min
Last Exit Home by Juniper Kite, 4 min
```

Nothing moved. Show-Song outputs sentences, and a sentence is only text: it has no Minutes for Sort-Object to sort by. The cmdlets you've used since Module 3 hand on **objects**, things with properties (*What an Object Is: `Get-Member`*), and your tools should too. This one outputs the songs themselves, the objects Import-Csv makes:

```powershell
function Get-Song {
    param(
        [string]$Mood,
        [string]$Path = 'road-trip.csv'
    )
    $songs = Import-Csv -Path $Path
    if ($Mood) {
        $songs = $songs | Where-Object Mood -eq $Mood
    }
    $songs
}
Get-Song -Mood Chill | Sort-Object Minutes
```

```text
Title          Artist         Minutes Mood
-----          ------         ------- ----
Last Exit Home Juniper Kite   4       Chill
Cruise Control The Night Owls 5       Chill
Rainy Overpass Juniper Kite   6       Chill
```

![The same three Chill songs sent into Sort-Object Minutes two ways: Show-Song sends three sentences, plain text with nothing to sort by, and they come out in the order they went in; Get-Song sends three song objects, each with a Title, Artist, Minutes and Mood, and they come out sorted by Minutes, 4, 5 and 6](https://fsdtrainingmedia.blob.core.windows.net/public/images/2026/11/d693fdbbddc5492eabfa1c2673653457.webp)

The `param()` block works exactly as a script's does (*Parameters: `param()`*): types, and a default value for `-Path`. `if ($Mood)` is true only when you gave a mood, so `Get-Song` on its own gets every song. The last line, `$songs` on its own, is the function's output. Now every pipeline you know works on your tool:

```powershell
(Get-Song | Measure-Object Minutes -Sum).Sum
Get-Song | Where-Object Artist -eq 'Maple Street'
```

```text
32

Title                  Artist       Minutes Mood
-----                  ------       ------- ----
Backseat Snacks        Maple Street 3       Upbeat
Left at the Lighthouse Maple Street 7       Focus
```

The rule: **output objects, and let whoever runs the tool decide how to show them.** Words meant only for the screen belong to `Write-Host` and `Write-Verbose` (*Where Output Goes: `Write-Output`, `Write-Host` and Friends*).

## Keep your tools in a file

A function typed at the prompt lasts until the window closes. Put Get-Song in a file instead: run `code PlaylistTools.ps1` in the practice folder, paste the Get-Song function without the line that runs it, and save. Then open a new PowerShell window and run the file the way you'd run a script:

```powershell
Set-Location "$HOME\terminal-practice\playlist-tools"
.\PlaylistTools.ps1
Get-Song -Mood Focus
```

```text
Get-Song: The term 'Get-Song' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
```

The script ran in a room of its own, made Get-Song there, and ended, and the room was cleared with Get-Song in it: the same thing that happened to `$snackBudget` in *Your Profile*. The fix is the same too. Put a dot and a space in front, called **dot-sourcing**, and the file runs in your own session, so whatever it makes stays:

```powershell
. .\PlaylistTools.ps1
Get-Song -Mood Focus
Get-Command -Noun Song
```

```text
Title                  Artist       Minutes Mood
-----                  ------       ------- ----
Left at the Lighthouse Maple Street 7       Focus

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Function        Get-Song
```

Each time you change the file, dot-source it again to load the new version. On a Mac or Linux, write `. ./PlaylistTools.ps1`. *Your Own Module* turns this file into a module.

**Try it.** In the first window, save the Upbeat songs with `Get-Song -Mood Upbeat | Export-Csv upbeat.csv`, and the same songs as text with `Show-Song -Mood Upbeat | Export-Csv upbeat-text.csv`. Open both with Get-Content. The text version kept only one fact about each sentence: its Length.

## Check yourself

2 questions to try on the lesson page.

## So what

A function with a cmdlet's name, real parameters and objects for output isn't only a shortcut any more: it's a tool other people can guess, pipe and build on.

## Key terms

- [Function](https://www.ask-codey.com/glossary/function-powershell)
- [Approved Verb](https://www.ask-codey.com/glossary/approved-verb)
- [Verb-Noun Naming](https://www.ask-codey.com/glossary/verb-noun-naming)
- [param Block](https://www.ask-codey.com/glossary/param-block)
- [Dot-Sourcing](https://www.ask-codey.com/glossary/dot-sourcing)

## Cheat sheets

- [Functions: Naming a Job](https://www.ask-codey.com/cheat-sheets/powershell-functions-cheat-sheet)

## Related

- [Aliases and Small Functions](https://www.ask-codey.com/lessons/powershell-aliases-and-small-functions)
- [Parameters: \`param()\`](https://www.ask-codey.com/lessons/powershell-param)
- [Verb-Noun: Names That Explain Themselves](https://www.ask-codey.com/lessons/powershell-verb-noun-names)
- [Advanced Functions: \`\[CmdletBinding()\]\`](https://www.ask-codey.com/lessons/powershell-advanced-functions)

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