Have you ever spent more time naming a script than actually writing it?

If you are anything like me, you know the feeling. Summer is here, and I could probably spend the entire holiday just finding the perfect name for my computer - let alone a PowerShell script or function. There is something about naming things that triggers a unique kind of stress. You want the name to be clear, descriptive, and professional, but you also want to move on and actually get work done. Add to that the constraints you face in other contexts - Azure resources that require lowercase names, unique identifiers, and strict character limits - and naming quickly becomes one of those small decisions that feels unreasonably difficult.

There are only two hard things in Computer Science: cache invalidation and naming things.

Phil Karlton

The good news is that PowerShell has a well-defined naming convention that takes much of the guesswork out of the equation. In my previous post about validating and improving your PowerShell scripts, I touched on code quality, PSScriptAnalyzer, and approved verbs. This post picks up where that guidance left off and focuses entirely on naming - how to choose the right verb, how to craft a meaningful noun, and how to apply these principles consistently across your scripts and functions.

Based on my experience writing and reviewing PowerShell code across multiple projects and organizations, here is what I have learned about getting names right.

The naming problem

The naming problem is universal in software development, and PowerShell is no exception. Whether you are naming a script file, a function, a variable, or a parameter, the same challenge applies: the name needs to communicate intent clearly and concisely.

Naming things is hard
Naming things is hard

In everyday IT work, you might encounter naming challenges everywhere:

  • Computer names - balancing descriptive meaning with character limits and organizational standards
  • Azure resources - lowercase only, globally unique, restricted characters, and length constraints
  • File names - choosing between Delete.ps1, cleanup-script.ps1, or something more descriptive
  • Function names - making sure your custom code is discoverable and consistent with built-in cmdlets

Some people resort to creative shortcuts like removing vowels or using GUIDs when they run out of ideas. While those approaches might solve uniqueness problems, they do nothing for readability. A script named RmOldFls.ps1 or a function called Do-Thing tells you almost nothing about what the code actually does.

PowerShell solves this elegantly with a convention that has been part of the language since day one: the verb-noun naming pattern.

The verb-noun naming convention

The verb-noun naming convention is the fundamental rule for naming PowerShell scripts and functions. Use a verb-noun pair that clearly indicates what the code does and what it acts on. If you have a script that creates a new user account, name it New-User.ps1. If you have a function that retrieves the status of a service, name it Get-ServiceStatus.

This convention has several benefits:

  • Consistency with built-in cmdlets. PowerShell’s own commands follow this pattern - Get-Process, Set-Item, Invoke-Command. When your custom code follows the same convention, it feels native.
  • Readability. You can quickly identify what a script or function does. Remove-ExpiredCertificate is immediately clear. DelCert.ps1 is not.
  • Discoverability. You can use Get-Command -Verb Get to find all commands that retrieve data, or Get-Command -Noun *User* to find everything related to users. Your custom functions become part of this ecosystem when you follow the convention.

Think of verb-noun naming as a contract with anyone who reads your code - including your future self. The verb tells them what action is performed. The noun tells them what is being acted on. Together, they form a self-documenting name.

How to choose the right verb

PowerShell defines a set of approved verbs that cover the most common actions. You should always use an approved verb rather than inventing your own. This is not just a recommendation - PSScriptAnalyzer will flag non-approved verbs, and Export-ModuleMember issues warnings when modules contain functions with unapproved verbs.

You can see all approved verbs by running:

# Description: Retrieves the complete list of approved PowerShell verbs
# Elevation is not required - This is a read-only query

Get-Verb | Sort-Object -Property Verb | Format-Table -Property Verb, Group, Description -AutoSize

Example: List all approved PowerShell verbs

The approved verbs are organized into groups that help you pick the right one:

GroupCommon verbsWhen to use
CommonGet, Set, New, RemoveMost everyday actions - retrieving, modifying, creating, deleting
DataImport, Export, ConvertMoving data between formats or locations
LifecycleStart, Stop, Restart, SuspendControlling the state of services, processes, or jobs
DiagnosticTest, Measure, DebugValidating, measuring, or troubleshooting
CommunicationSend, Receive, ConnectNetwork and communication operations
SecurityGrant, Revoke, ProtectPermission and security operations
Approved verb groups and common verbs

Common verb mistakes

Common verb mistakes appear frequently in code I review - here is what to use instead:

Instead ofUseWhy
Delete-FileRemove-File“Delete” is not an approved verb. “Remove” is the standard.
Change-PasswordSet-Password“Change” is not approved. “Set” covers modification actions.
Run-ScriptInvoke-Script“Run” is not approved. “Invoke” is the standard for executing commands.
Create-UserNew-User“Create” is not approved. “New” is the standard for creating resources.
List-ServiceGet-Service“List” is not approved. “Get” covers retrieval actions.
Check-StatusTest-Status“Check” is not approved. “Test” is the standard for validation.
Common verb mistakes and their approved alternatives

When you are unsure which verb to use, ask yourself: “What is the closest built-in cmdlet that does something similar?” If you are writing something similar to Get-Process, use Get. If it is similar to Invoke-Command, use Invoke. The built-in cmdlets are your best reference.

How to choose a meaningful noun

The noun is where you describe what the verb acts on. A good noun is specific, descriptive, and uses singular form.

Use singular nouns

PowerShell convention uses singular nouns. The cmdlet is Get-Process, not Get-Processes - even though it often returns multiple objects. This is because the noun describes the type of object, not the quantity:

# These all use singular nouns, even when returning collections
Get-Process          # Returns multiple processes
Get-Service          # Returns multiple services
Get-ChildItem        # Returns multiple items

Example: Singular nouns with plural results

Follow the same pattern in your custom code. Use Get-ExpiredCertificate rather than Get-ExpiredCertificates.

Be specific, not generic

Avoid vague or generic nouns. The more specific you are, the more useful the name becomes:

Vague nameBetter nameWhy it is better
Get-DataGet-DeviceComplianceReportDescribes exactly what data is retrieved
Set-ItemSet-RegistryBaselineSpecifies the type of item being configured
Remove-ObjectRemove-StaleDeviceRecordClarifies what kind of object is removed
Test-ThingTest-NetworkConnectivityIdentifies what is being tested
Vague nouns versus specific nouns

Use PascalCase for compound nouns

When your noun consists of multiple words, use PascalCase - capitalize the first letter of each word with no separator:

  • Get-ServiceStatus (not Get-Service-Status or Get-servicestatus)
  • Remove-ExpiredCertificate (not Remove-Expired-Certificate)
  • Set-DeviceCompliancePolicy (not Set-devicecompliancepolicy)

This is the same casing convention used by all built-in PowerShell cmdlets and .NET types.

Naming your script files

Script file names should follow the same verb-noun pattern as functions. Instead of vague names like script1.ps1 or cleanup.ps1, use names that describe the action and the target:

Bad nameGood nameWhat it tells you
script.ps1Remove-ExpiredLogFile.ps1Removes log files that have expired
fix.ps1Repair-BrokenGroupMembership.ps1Fixes group membership issues
deploy.ps1Install-CompanyApplication.ps1Installs a specific application
update.ps1Update-DeviceFirmware.ps1Updates firmware on a device
report.ps1Export-ComplianceReport.ps1Exports a compliance report
Poor script names versus descriptive verb-noun names

When you name script files this way, you get the same benefits described earlier - consistency, readability, and discoverability - applied directly to your file system. Finding the right script in a folder becomes trivial when all your Get-* scripts group together, and the file name itself tells you what the script does without needing to open it.

Script file naming rules

Script file naming rules are straightforward when you follow a few key conventions:

  • Use the verb-noun pattern: Verb-Noun.ps1
  • Use PascalCase: Get-DeviceInventory.ps1, not get-deviceinventory.ps1
  • Use a dash to separate verb and noun: Get-DeviceInventory.ps1, not Get_DeviceInventory.ps1 or GetDeviceInventory.ps1
  • Keep the .ps1 extension (or .psm1 for modules)
  • Avoid spaces, special characters, and excessively long names

Naming your functions

Functions follow the same verb-noun convention as scripts, but there are additional considerations when writing functions that will be part of a module or shared with others.

Match the function name to its purpose

Matching the function name to its purpose means every function should do one thing, and its name should describe that one thing clearly:

# Description: Examples of well-named functions
# Elevation is not required - These are function definitions only

function Get-DeviceComplianceStatus {
    <#
    .SYNOPSIS
        Retrieves the compliance status for a specified device.
    #>
    param (
        [Parameter(Mandatory)]
        [string]$DeviceId
    )
    # Function logic here
}

function Set-AutopilotGroupTag {
    <#
    .SYNOPSIS
        Updates the group tag for a Windows Autopilot device.
    #>
    param (
        [Parameter(Mandatory)]
        [string]$SerialNumber,
        [Parameter(Mandatory)]
        [string]$GroupTag
    )
    # Function logic here
}

function Test-IntuneEnrollmentRestriction {
    <#
    .SYNOPSIS
        Validates whether a device meets enrollment restriction criteria.
    #>
    param (
        [Parameter(Mandatory)]
        [string]$DeviceId
    )
    # Function logic here
}

Example: Well-named functions with clear purposes

Use a namespace prefix for custom modules

When building a module, consider adding a short prefix to your nouns to avoid conflicts with built-in cmdlets and other modules. Microsoft itself does this - the Microsoft Graph PowerShell module uses Mg as a prefix:

# Without prefix - risks collision with other modules
function Get-DeviceStatus { }

# With prefix - clearly belongs to your module
function Get-CorpDeviceStatus { }
function Set-CorpDeviceBaseline { }
function Test-CorpDeviceCompliance { }

Example: Using a namespace prefix in a custom module

This pattern makes it clear which module a command belongs to, especially in environments where many modules are loaded simultaneously.

Avoid aliases in scripts and functions

Avoiding aliases in scripts and functions is an important habit for writing readable, portable code. While PowerShell supports aliases like gci for Get-ChildItem or % for ForEach-Object, they are convenient for interactive use in the console, but in scripts they reduce readability and can cause issues in environments with restricted language modes.

PSScriptAnalyzer will flag alias usage in scripts through the PSAvoidUsingCmdletAliases rule. If you have PSScriptAnalyzer integrated into Visual Studio Code - as covered in my post on validating and improving your PowerShell scripts - you will see warnings highlighted in real time as you type. Always use the full cmdlet names:

# Bad - using aliases
gci C:\Logs | ? { $_.LastWriteTime -lt (Get-Date).AddDays(-30) } | rm

# Good - using full cmdlet names
Get-ChildItem -Path "C:\Logs" |
    Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-30) } |
    Remove-Item

Example: Avoid aliases in scripts

Parameters and variables

Parameters and variables deserve the same naming attention as scripts and functions.

Parameter naming

Parameters should be descriptive and use PascalCase. Follow these guidelines:

  • Use common parameter names from built-in cmdlets when the meaning is the same: $Path, $Name, $ComputerName, $Credential, $Force.
  • Be specific: $LogFilePath is better than $Path when the parameter specifically expects a log file location.
  • Avoid abbreviations: $ComputerName not $CN, $UserPrincipalName not $UPN.
# Description: Function demonstrating clear parameter naming
# Elevation is not required - This is a function definition only

function Export-DeviceComplianceReport {
    param (
        [Parameter(Mandatory)]
        [string]$OutputPath,

        [Parameter()]
        [datetime]$StartDate = (Get-Date).AddDays(-30),

        [Parameter()]
        [datetime]$EndDate = (Get-Date),

        [Parameter()]
        [string[]]$DeviceGroupFilter,

        [Parameter()]
        [switch]$IncludeNonCompliant
    )
    # Function logic here
}

Example: Descriptive parameter names

Variable naming

Variable naming within your scripts should follow the same principle of clarity. Use descriptive names and camelCase or PascalCase consistently:

# Bad - cryptic variable names
$x = Get-Date
$d = $x.AddDays(-30)
$f = Get-ChildItem -Path "C:\Logs" | Where-Object { $_.LastWriteTime -lt $d }

# Good - descriptive variable names
$currentDate = Get-Date
$thresholdDate = $currentDate.AddDays(-30)
$expiredLogFiles = Get-ChildItem -Path "C:\Logs" |
    Where-Object { $_.LastWriteTime -lt $thresholdDate }

Example: Clear variable names

Descriptive variable names make your code self-documenting. When you revisit a script six months later - or when a colleague picks it up for the first time - clear names save significant time.

Validating your naming choices

PowerShell provides built-in tools to validate your naming conventions. PSScriptAnalyzer is your best friend here, and if you followed my earlier post on setting up a well-configured repository, you already have it integrated into your Visual Studio Code workflow.

Check for approved verbs

You can quickly check whether a verb is approved:

# Description: Checks if a specific verb is in the approved verbs list
# Elevation is not required - This is a read-only query

Get-Verb -Verb "Remove"
# Returns the verb if approved, empty if not

Get-Verb -Verb "Delete"
# Returns empty - "Delete" is not an approved verb

Example: Validate a verb against the approved list

Use PSScriptAnalyzer rules

PSScriptAnalyzer includes specific rules for naming:

# Description: Analyzes a script for naming convention violations
# Elevation is not required - This is a read-only analysis

Invoke-ScriptAnalyzer -Path ".\MyScript.ps1" -IncludeRule @(
    'PSUseApprovedVerbs',
    'PSUseSingularNouns'
)

Example: Run PSScriptAnalyzer naming rules on a script

The PSUseApprovedVerbs rule checks that all exported functions use approved verbs. The PSUseSingularNouns rule checks that nouns are singular. Together, these rules catch the most common naming mistakes before they become habits.

Quick reference

Here is a summary of the key naming conventions covered in this post:

AreaConventionExample
Script filesVerb-Noun.ps1 in PascalCaseRemove-ExpiredLogFile.ps1
FunctionsVerb-Noun in PascalCaseGet-DeviceComplianceStatus
VerbsUse approved verbs onlyGet, Set, New, Remove
NounsSingular, specific, PascalCaseDeviceComplianceStatus
ParametersPascalCase, descriptive$OutputPath, $DeviceGroupFilter
VariablesDescriptive, consistent casing$expiredLogFiles, $thresholdDate
Module prefixShort namespace prefixGet-CorpDeviceStatus
Quick reference for PowerShell naming conventions

The wrap

Naming things is genuinely hard - there is a reason it shows up on every list of the most difficult challenges in computer science. But PowerShell’s verb-noun convention gives you a solid framework that removes much of the ambiguity. When you follow the approved verbs, use specific singular nouns, and apply consistent PascalCase formatting, your code becomes easier to read, discover, and maintain.

The next time you find yourself staring at a blinking cursor, trying to decide between Delete-OldStuff.ps1 and Cleanup.ps1, remember: use an approved verb, pick a descriptive noun, and move on. Your summer holiday is too short to spend it naming things.

Happy coding.

–Jesper

Header image attribution: Image created with help from Adobe Firefly