I would like your opinion on my Remove-Files
PowerShell function. It is used in my File-Removal-PowerShell-Script. It is designed to be very flexible so a script user can have configure it to remove files in multiple and various way as it often the chase.
Remove-Files function
function Remove-Files {
[CmdletBinding(SupportsShouldProcess = $true)]
[OutputType([PSCustomObject])]
param (
[Parameter(Position = 0, Mandatory, ValueFromPipelineByPropertyName)]
[string]
$FolderPath,
[Parameter(Position = 1, Mandatory, ValueFromPipelineByPropertyName)]
[string]
$FileName,
[Parameter(Position = 2, ValueFromPipelineByPropertyName)]
[int]
$OlderThen = 0,
[Parameter(Position = 3, ValueFromPipelineByPropertyName)]
[string]
$Recurse = "false",
[Parameter(Position = 4, ValueFromPipelineByPropertyName)]
[string]
$Force = "false"
)
begin {
$DateToDelete = (Get-Date).AddDays(- $OlderThen)
}
process {
$FolderSpaceFreed = 0
$FilesRemoved = 0
$FailedRemovals = 0
if (-not (Test-Path -Path $FolderPath)) {
Write-Log -Message "ERROR: $FolderPath folder does not exist"
return
}
$FullPath = Join-Path -Path $FolderPath -ChildPath $FileName
if ($Recurse -eq "true") {
$FileList = Get-ChildItem -Path $FullPath -Recurse
}
else {
$FileList = Get-ChildItem -Path $FullPath
}
$FileList = $FileList | Where-Object {$_.LastWriteTime -lt $DateToDelete}
foreach ($File in $FileList) {
$FileSize = (Get-Item -Path $File.FullName).Length
$SpaceFreed = Get-FormattedFileSize -Size $FileSize
if ($Force -eq "true") {
Get-Item -Path $File.FullName | Remove-Item -Force
}
else {
Get-Item -Path $File.FullName | Remove-Item
}
if (-not (Test-Path -Path $File.FullName)) {
$Message = "Successfully deleted " + $File.Name + " file - removed $SpaceFreed"
$FolderSpaceFreed += $FileSize
$FilesRemoved ++
}
else {
$Message = "Failed to delete " + $File.Name + " file"
$FailedRemovals ++
}
Write-Log -Message $Message
}
$SpaceFreed = Get-FormattedFileSize -Size $FolderSpaceFreed
if ($FilesRemoved -gt 0) {
Write-Log -Message "Successfully deleted $FilesRemoved files in $FolderPath folder, and $SpaceFreed of space was freed"
}
if ($FailedRemovals -gt 0) {
Write-Log -Message "Failed to delete $FailedRemovals files in $FolderPath folder"
}
if ($FilesRemoved -eq 0 -and $FailedRemovals -eq 0) {
Write-Log -Message "No files for delition were found in $FolderPath folder"
}
New-Object -TypeName psobject -Property @{
FolderSpaceFreed = $FolderSpaceFreed
FilesRemoved = $FilesRemoved
FailedRemovals = $FailedRemovals
}
}
}
Before someone says anything about it, I have to tell you why I did not use a switch
type for -Recurse
and -Force
parameters, and it is because the function is feed from .csv
file with data, and I did not find a elegant way to pass string value to a switch
parameter.
1 Answer 1
I have found a way to use pass string values to switch parameters to Remove-Files
function so I have refactored the function ho have two switch parameters.
The new version
function Remove-Files {
[CmdletBinding(SupportsShouldProcess = $true)]
[OutputType([PSCustomObject])]
param (
[Parameter(Mandatory = $true,
Position = 0,
ParameterSetName = "FolderPath",
ValueFromPipeline = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = "Full folder path in which file/files are to be deleted")]
[string]
$FolderPath,
[Parameter(Mandatory = $true,
Position = 1,
ParameterSetName = "FileName",
ValueFromPipeline = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = "File name that can include wildcard character")]
[SupportsWildcards()]
[string]
$FileName,
[Parameter(Mandatory = $false,
Position = 2,
ParameterSetName = "OlderThen",
ValueFromPipeline = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = "Number of days to delete files older than that")]
[int]
$OlderThen = 0,
[Parameter(Mandatory = $false,
Position = 3,
ParameterSetName = "Recurse",
ValueFromPipeline = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = "Switch on to file remove files in subfolders")]
[switch]
$Recurse = $false,
[Parameter(Mandatory = $false,
Position = 4,
ParameterSetName = "Force",
ValueFromPipeline = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = "Switch on to force remove files")]
[switch]
$Force = $false
)
process {
$FolderSpaceFreed = 0
$FilesRemoved = 0
$FailedRemovals = 0
if (-not (Test-Path -Path $FolderPath)) {
Write-Log -Message "ERROR: $FolderPath folder does not exist"
return
}
$FullPath = Join-Path -Path $FolderPath -ChildPath $FileName
if ($Recurse) {
$FileList = Get-ChildItem -Path $FullPath -Recurse
}
else {
$FileList = Get-ChildItem -Path $FullPath
}
$DateToDelete = (Get-Date).AddDays(- $OlderThen)
$FileList = $FileList | Where-Object {$_.CreationTime -lt $DateToDelete}
foreach ($File in $FileList) {
$FileSize = (Get-Item -Path $File.FullName).Length
$SpaceFreed = Get-FormattedFileSize -Size $FileSize
if ($Force) {
Get-Item -Path $File.FullName | Remove-Item -Force
}
else {
Get-Item -Path $File.FullName | Remove-Item
}
if (-not (Test-Path -Path $File.FullName)) {
$Message = "Successfully deleted " + $File.Name + " file - removed $SpaceFreed"
$FolderSpaceFreed += $FileSize
$FilesRemoved ++
}
else {
$Message = "Failed to delete " + $File.Name + " file"
$FailedRemovals ++
}
Write-Log -Message $Message
}
$SpaceFreed = Get-FormattedFileSize -Size $FolderSpaceFreed
if ($FilesRemoved -gt 0) {
Write-Log -Message "Successfully deleted $FilesRemoved files in $FolderPath folder, and $SpaceFreed of space was freed"
}
if ($FailedRemovals -gt 0) {
Write-Log -Message "Failed to delete $FailedRemovals files in $FolderPath folder"
}
if ($FilesRemoved -eq 0 -and $FailedRemovals -eq 0) {
Write-Log -Message "No files for delition were found in $FolderPath folder"
}
New-Object -TypeName psobject -Property @{
FolderSpaceFreed = $FolderSpaceFreed
FilesRemoved = $FilesRemoved
FailedRemovals = $FailedRemovals
}
}
}
... -Force:$($Force -eq "true")
is a possible way to pass a[string]$Force
value to the-Force
switch parameter... \$\endgroup\$