Have you ever wanted to create a PowerShell cmdlet but didn’t know C# or another Microsoft .NET Framework language? Why keep ‘wanting’ when you have PowerShell
CmdletBinding
at your fingertips?
Not a reader? Watch this related video tutorial!
There are cases where you might have so many files of different types in a directory without a good organization. Keeping your files organized is always a good practice, so you’ll create a basic function to move files by file extensions to a specified folder.
A basic PowerShell
function
is not defined as having just a few lines of code. “Basic” in this context means that the function lacks the features of a PowerShell cmdlet. The function doesn’t have common parameters, and there’s no full control over the parameters available.
2. Copy and paste the code below to the code editor, and run the code. The code below moves all
.pdf
,
.doc
, and
.txt
files on your Desktop to a single folder called Documents.
From this point throughout this tutorial, be sure to replace ADMIN in the Desktop folder path (C:\Users\ADMIN\Desktop\) with your computer username.
Function Group-Files
Param(
[string]$Path,
[string]$Folder
# Check if the destination folder exists. If not, then create it
If ((Test-Path -Path ($Path + "\" + $Folder)) -eq $False) {
New-Item -Name $Folder -Path $Path -ItemType Directory
# Move Items
Get-ChildItem $Path | ForEach-Object {
# If the last four characters of the filename ends with .pdf, .doc, .txt
If ($_.FullName.Substring($_.FullName.Length -4) -in ".pdf", ".doc", ".txt")
Move-Item -Path $_.FullName -Destination ($Path + $Folder)
# Call the Group-Files function
Group-Files -Path C:\Users\ADMIN\Desktop\ -Folder "Documents"
After running the code above, you may have noticed that all the files just moved without asking you to confirm. Moreover, the function didn’t tell you what would happen if you ran the code. You’ll learn more about enhancing the function with CmdletBinding in the following sections.
3. Lastly, run the
Get-Command
below to list all the parameters available for the Group-Files function you created.
(Get-Command Group-Files).Parameters
Gaining Access to Common Parameters with the CmdletBinding Attribute
You’ve seen that a basic function works fine. But perhaps you prefer to make parameters mandatory or add a confirm action dialog box? If so, the
CmdletBinding
attribute will do the trick! The
CmdletBinding
attribute allows you to use common parameters available for PowerShell cmdlets.
The following code represents the syntax of the
CmdletBinding
attribute, including all its arguments.
[CmdletBinding(
ConfirmImpact=<string>,
# Default parameter set name you want PowerShell to use
# if there is no parameter set.
DefaultParameterSetName=<string>,
# uri to online help, must begin with http or https
HelpURI=<uri>,
# Used when you’re trying to return data from a large database suchas MySQL.
SupportsPaging=<boolean>,
# Adds three parameters – First, Skip, and IncludeTotalCount to the function.
SupportsShouldProcess=<boolean>,
# positional binding binds positions to parameters
PositionalBinding=<boolean>) as defined
# It's important to use the Param keyword
Param ($Parameter1)
Begin{}
Process{}
End{}
Function Group-Files
{ # Set SupportsShouldProcess to True, to make -WhatIf and -Confirm accessible
[CmdletBinding(SupportsShouldProcess=$True)]
Param(
[string]$Path,
[string]$Folder
If ($PSCmdlet.ShouldProcess($Path)) {
Write-Host "WhatIf wasn't used, moving files..."
Else {
Write-Host "WhatIf has been used! Doing nothing..."
# Calls the Grou-File function
Group-Files -Path C:\\Users\\ADMIN\\Desktop\\ -Folder "Documents" -WhatIf
Function Group-Files
# Set SupportsShouldProcess to True to make -WhatIf and -Confirm accessibly
[CmdletBinding(SupportsShouldProcess=$True)]
Param([string]$Path, [string]$Folders)
# If the user confirmed Yes, or user didn't use -Confirm
If ($PSCmdlet.ShouldProcess($Path)) {
Write-Host "Files Moved"
# If the user confirmed No
Else {
Write-Host "Action Declined"
# Calls the Group-Files function
Group-Files -Path C:\\Users\\ADMIN\\Desktop\\ -Folder "Documents" -Confirm
None – PowerShell will not prompt confirmation for any actions unless you use the -Confirm switch.
Low – Actions with low, medium, or high risk will be automatically confirmed.
Medium – The default level of the ConfirmImpact argument, where PowerShell prompts confirmation for actions with medium or high risk, such as deleting files.
High – PowerShell prompts the user as if the function was called with the -Confirm parameter.
Now, run the code below to see how the ConfirmImpact argument and the preference $ConfirmPreference variable work side-by-side.
The action of ConfirmImpact depends on the $ConfirmPreference variable’s value. You’ll get a confirmation prompt if you set the ConfirmImpact level equal to or greater than the $ConfirmPreference variable’s value.
$ConfirmPreference='High' # Sets confirmation preference
Function Group-Files
# Sets -WhatIf, -Confirm and ConfirmImpact accessible
[CmdletBinding(SupportsShouldProcess=$True, ConfirmImpact='High')]
Param([string]$Path, [string]$Folders)
# If the user confirmed Yes, or user didn't use -Confirm
If ($PSCmdlet.ShouldProcess($Path)) {
Write-Host "Files Moved"
# If the user confirmed No
Else {
Write-Host "Action Declined"
# Calls the Group-Files function
Group-Files -Path C:\\Users\\ADMIN\\Desktop\\ -Folder "Documents"
Param([string]$Path, [string]$Folder)
Write-Verbose "Creating the folder if it doesn't exist..."
# If the user confirmed Yes, or user didn't use -Confirm switch
If ($PSCmdlet.ShouldProcess($Path)) {
Write-Host "Files will be moved"
Write-Verbose "Moving files..."
# If the user confirmed No
Else {
Write-Host "Files will not be moved"
# Calls the Group-Files function
Group-Files -Path C:\\Users\\ADMIN\\Desktop\\ -Folder "Documents"
For instance, running the Group-Files function will not work without parameters, so you’ll set the $Path parameter as mandatory. At the same time, you’ll set a default value for the $Folders parameter.
Below is the syntax for the Parameter attribute and all its arguments.
Param
[Parameter(
Mandatory=<Boolean>,
Position=<Integer>,
ParameterSetName=<String>,
ValueFromPipeline=<Boolean>,
ValueFromPipelineByPropertyName=<Boolean>,
ValueFromRemainingArguments=<Boolean>,
HelpMessage=<String>,
[string[]]
$Parameter1
Mandatory=$True,
Position=0,
# Since the Path parameter can also get its value from a pipeline input,
# provide access to the pipeline input
ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$True
[string]$Path,
[Parameter(
Mandatory=$False,
Position=1
[string]$Folder = "Documents" # Default value of $Folder parameter
# If the user confirmed Yes, or user didn't use -Confirm
If ($PSCmdlet.ShouldProcess($Path)) {
Write-Host "Files will be moved"
Write-Verbose "Moving files..."
# If the user confirmed No
Else {Write-Host "Files will not be moved"}
# Calls the Group-Files function without the -Path parameter
Group-Files -Folder "Documents"
[CmdletBinding(
SupportsShouldProcess=$True, # Allows the use of -Confirm and -Whatif
PositionalBinding=$True, # Binds Path and Folder by their position
ConfirmImpact="Medium" # Confirms before moving files
Param(
[Parameter(
Mandatory=$True,
ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$True,
HelpMessage="Enter a source folder path"
# Validate the path is a folder and not a file
[ValidateScript({Test-Path $_ -PathType Container})]
[String]$Path,
[Parameter(
Mandatory=$False,
HelpMessage="Enter a destination path"
[ValidateCount(1,1)] # Must provide 1 argument/folder name
[String]$Folder = "Documents"
Begin {
# Uncomment the line below to activate -whatif
# $WhatIfPreference = $True
# Uncomment the line below not to ask for confirmation when moving each file
# $ConfirmPreference = "High"
# Contains the main part of the function
Process {
# Check if folders exist. If not, then create them
If ((Test-Path -Path ($Path + "\\" + $Folder)) -eq $False) {
#Write-Host ($Path+"\\"+$_) does not exist!
Write-Verbose "Creating folder $($Path+"\\"+$Folder) since it does not exist."
New-Item -Name $Folder -Path $Path -ItemType Directory
# Debug message
Write-Debug "Make sure files are not opened with any program before moving."
# If the user confirmed Yes, or user didn't use -Confirm
If ($PSCmdlet.ShouldProcess($Path)) {
Write-Host "Files will be moved"
# Get all the files in the $Path directory
Write-Verbose "Moving files..."
Get-ChildItem $Path | ForEach-Object {
# Documents
If ($_.FullName.Substring($_.FullName.Length -4) -in ".pdf", ".doc", ".txt") {
Write-Verbose "Moving file $($_.FullName) to $($Path + $Folder)"
Move-Item -Path $_.FullName -Destination ($Path + $Folder)
# If the user confirmed No
Else {
Write-Host "Files will not be moved"
# Call the Group-Files function
Group-Files -Verbose -Debug
Hate ads? Want to support the writer? Get many of our tutorials packaged as an ATA Guidebook.