PowerShell Verb-Noun Naming: Function Best Practices

PowerShell’s design philosophy centers on discoverability, and nothing defines that more than its mandatory Verb-Noun naming convention. Following powershell function verb-noun best practices keeps your modules consistent, eliminates import warnings, and makes your functions findable by anyone who runs Get-Command. This guide covers the approved verb list, how to choose between similar verbs, noun conventions, and how to refactor legacy functions without breaking callers.
The Full Get-Verb Approved Verb List Explained
The approved verb list is divided into functional groups. Choosing the right group is just as important as choosing the right verb — it sets user expectations about what a function does.
# View all approved verbs grouped by category
Get-Verb | Sort-Object Group, Verb | Format-Table Verb, Group, Description -AutoSize
# Find verbs in a specific group
Get-Verb | Where-Object Group -eq 'Data' | Select-Object Verb, Description
# Check whether a specific verb is approved
$verb = 'Fetch'
$isApproved = [bool](Get-Verb | Where-Object Verb -eq $verb)
Write-Host "'$verb' approved: $isApproved"
The major groups you’ll use most often are:
- Common — Add, Clear, Close, Copy, Enter, Exit, Find, Format, Get, Hide, Join, Lock, Move, New, Open, Optimize, Pop, Push, Redo, Remove, Rename, Reset, Resize, Search, Select, Set, Show, Skip, Split, Step, Switch, Undo, Unlock, Watch
- Data — Backup, Checkpoint, Compare, Compress, Convert, ConvertFrom, ConvertTo, Dismount, Edit, Expand, Export, Group, Import, Initialize, Limit, Merge, Mount, Out, Publish, Restore, Save, Sync, Unpublish, Update
- Lifecycle — Approve, Assert, Build, Complete, Confirm, Deny, Deploy, Disable, Enable, Install, Invoke, Register, Request, Restart, Resume, Start, Stop, Submit, Suspend, Uninstall, Unregister, Wait
- Diagnostic — Debug, Measure, Ping, Repair, Resolve, Test, Trace
Choosing Between Similar Verbs: Get vs Read, Set vs Update
Several approved verbs are near-synonyms, and picking the wrong one sends false signals to users about side effects. The distinctions matter.
# Get — retrieves data, no side effects, can be called repeatedly safely
function Get-ServerUptime { ... }
# Read — consumes or reads from a sequential source (file, stream, input)
function Read-LogFile { ... }
# Set — replaces an existing property or configuration completely
function Set-UserDepartment { ... }
# Update — modifies one or more properties of an existing object without full replacement
function Update-UserContactInfo { ... }
# New — creates a brand-new object or resource
function New-ServiceAccount { ... }
# Add — appends to or associates with an existing collection or resource
function Add-GroupMember { ... }
Rule of thumb: if the operation is idempotent and read-only, use Get. If it reads from a sequential data source, use Read. If it replaces a value entirely, use Set. If it partially modifies, use Update.
Noun Singularity and Prefix Conventions for Modules
Nouns should be singular (User, not Users) and should carry a module-specific prefix to avoid name collisions when users import multiple modules into the same session.
# Without prefix — collision risk when two modules define Get-User
function Get-User { ... }
# With module prefix (e.g., 'Acme' for internal modules, 'PS' for community modules)
function Get-AcmeUser { ... }
function New-AcmeUser { ... }
function Remove-AcmeUser { ... }
# The module manifest registers the prefix — callers can also import with -Prefix
Import-Module AcmeTools -Prefix Corp
# Now accessible as Get-CorpUser, New-CorpUser etc.
# Verify noun consistency across a module
Get-Command -Module AcmeTools |
ForEach-Object { ($_.Name -split '-')[1] } | # extract noun
Group-Object | Sort-Object Count -Descending | Format-Table -AutoSize
The prefix convention is especially important for modules published to the Gallery — PSGallery modules without a prefix frequently conflict with first-party Microsoft cmdlets.
Impact of Non-Approved Verbs on Import-Module Warnings
When PowerShell imports a module that exports functions with non-approved verbs, it emits a WARNING to the user’s console. While the module still loads, the warning erodes trust and fails PSScriptAnalyzer checks in CI.
# Simulate the warning by creating a temporary module
$tempModule = @'
function Fetch-Data { "data" }
function Check-Status { $true }
'@
$tempModule | Out-File "$env:TEMP\BadVerbs.psm1"
Import-Module "$env:TEMP\BadVerbs.psm1"
# WARNING: The names of some imported commands include unapproved verbs...
# Verify what warnings would fire before publishing
Invoke-ScriptAnalyzer -Path "$env:TEMP\BadVerbs.psm1" -IncludeRule PSUseApprovedVerbs
Refactoring Legacy Functions to Compliant Names
When renaming exported functions in a module, you risk breaking existing scripts that call the old name. Use aliases to provide a transition period.
# Old non-compliant name
# function Verify-Certificate { ... }
# Step 1 — rename to approved verb
function Test-Certificate {
[CmdletBinding()]
param([string]$Thumbprint)
# implementation
}
# Step 2 — create backward-compat alias
New-Alias -Name Verify-Certificate -Value Test-Certificate
# Step 3 — export both from the module manifest
# FunctionsToExport = @('Test-Certificate')
# AliasesToExport = @('Verify-Certificate')
# Step 4 — deprecate in help
<#
.NOTES
Verify-Certificate is a deprecated alias. Use Test-Certificate instead.
#>
Aliases as Backward Compatibility Bridges
Aliases let you rename public functions without immediately breaking consumers. Document them clearly and set a removal timeline in the module changelog.
# Define all aliases in a dedicated Aliases.ps1 file in your module
$aliases = @{
'Verify-Certificate' = 'Test-Certificate'
'Create-Report' = 'New-Report'
'Delete-OldFiles' = 'Remove-OldFiles'
}
foreach ($oldName in $aliases.Keys) {
if (-not (Get-Alias $oldName -ErrorAction SilentlyContinue)) {
New-Alias -Name $oldName -Value $aliases[$oldName] -Description 'Deprecated alias'
}
}
Common Errors and Fixes
Using ‘Check’ or ‘Verify’ verbs that are not on the approved list. Both are extremely common in legacy scripts. Replace with Test- (Diagnostic group), which carries the same semantic meaning and is widely understood. Get-Verb | Where-Object Verb -eq 'Test' confirms it is approved.
Forgetting that noun prefix must be consistent across all functions in a module. A module that exports Get-AcmeUser and Get-Server (without prefix) will confuse import with -Prefix and trip up PSScriptAnalyzer’s PSUseSingularNouns rule. Establish the prefix in the module manifest’s DefaultCommandPrefix field and enforce it in all function names.
Related Cmdlets / See Also
Wrapping Up
Verb-Noun naming is not bureaucracy — it is the contract between your code and every tool that discovers, documents, and tests PowerShell functions. Use Get-Verb to pick the right verb, add a module prefix to every noun, and use aliases to migrate legacy callers gracefully. Your module’s import experience will be warning-free and your functions will be discoverable with a simple Get-Command -Verb.


