I'm writing a Powershell 5.1 script that has to delete files from a folder, with a few exceptions. I want to supply the list of exceptions as a parameter. For example: "*.zip, *.log": delete everything except files that have the extension .zip or .log.
Seems simple enough:
param([string]$folder, [string[]]$exceptions)
remove-item "$folder\*" -Recurse -Force -Exclude @($exceptions)
To call the script:
ps -ExecutionPolicy Unrestricted -File "C:\scripts\deletefiles_custom.ps1" "C:\Test\" -exceptions "*.zip, *.log"
I've tried a whole bunch of variations, but nothing works. Either all files are deleted, or no files are deleted. I can get it to work when I specify a single item ("*.zip") as the exception, but it fails when I add the second item.
I've tried variations of the call:
ps -ExecutionPolicy Unrestricted -File "C:\scripts\deletefiles_custom.ps1" "C:\Test\" -exceptions "'*.zip', '*.log'"
Those don't help. How can I get this to work?
I'm writing a Powershell 5.1 script that has to delete files from a folder, with a few exceptions. I want to supply the list of exceptions as a parameter. For example: "*.zip, *.log": delete everything except files that have the extension .zip or .log.
Seems simple enough:
param([string]$folder, [string[]]$exceptions)
remove-item "$folder\*" -Recurse -Force -Exclude @($exceptions)
To call the script:
ps -ExecutionPolicy Unrestricted -File "C:\scripts\deletefiles_custom.ps1" "C:\Test\" -exceptions "*.zip, *.log"
I've tried a whole bunch of variations, but nothing works. Either all files are deleted, or no files are deleted. I can get it to work when I specify a single item ("*.zip") as the exception, but it fails when I add the second item.
I've tried variations of the call:
ps -ExecutionPolicy Unrestricted -File "C:\scripts\deletefiles_custom.ps1" "C:\Test\" -exceptions "'*.zip', '*.log'"
Those don't help. How can I get this to work?
An issue as stated in comments is that "*.zip, *.log"
is a single string not an array, ideally calling your script using an array: "*.zip", "*.log"
should solve the problem, but it isn't the case. Because you're calling your script from the PowerShell CLI, passing-in an array as argument gets tricky, to troubleshoot the issue you could change your script to:
param([string] $Folder, [string[]] $Exceptions)
$PSBoundParameters
From here, if you call the script from PowerShell itself using an array for the second argument:
powershell -nop -f .\deletefiles_custom.ps1 "some\folder\" "*.zip", "*.log"
You'd get the following output:
Key Value
--- -----
Folder some\folder\
Exceptions {*.zip}
So as you can see, the second argument for -Exceptions
was lost. Solution to this problem is to decorate the -Exceptions
parameter with ValueFromRemainingArguments
:
param([string] $Folder, [Parameter(ValueFromRemainingArguments)] [string[]] $Exceptions)
$PSBoundParameters
Now if we try the same call again we should get the expected output:
Key Value
--- -----
Folder some\folder\
Exceptions {*.zip, *.log}
So far, the issue if calling the script thru the PowerShell CLI from PowerShell itself should be fixed, however there is yet another problem if calling the script from CMD, if you try the same call from CMD you would see the following output:
Key Value
--- -----
Folder some\folder" *.zip, *.log
And this happens because the last \
in the -Folder
argument requires escaping, meaning:
powershell -nop -f .\deletefiles_custom.ps1 "some\folder\\" "*.zip", "*.log"
Otherwise that backslash escapes the "
making it a single argument. So, in summary, if you're calling the script from CMD or Task Scheduler, ensure you're either escaping that last \
or just remove it. Then current code you already have adding the ValueFromRemainingArguments
to -Exceptions
should fix the issue.
Use
param([string]$folder, [string[]]$exceptions)
Get-ChildItem -File -Path $folder |
Where-Object -Property Extension -NotIn $exceptions |
# remove the -WhatIf parameter once you are sure
# that everything is working as expected.
Remove-Item -WhatIf
and call it as
powershell -ExecutionPolicy Unrestricted -File 'C:\scripts\deletefiles_custom.ps1' 'C:\Test\' -exceptions '.zip', '.log'
Note how the single elements of the exception list are quoted, not the whole list.
Quoting the whole list would pass it as a "single string".
Get-ChildItem
to discover the files to delete, then filter usingWhere-Object
:Get-ChildItem -File -Recurse -Force |Where-Object Extension -notin '.zip','.log' |Remove-Item
– Mathias R. Jessen Commented Jan 29 at 15:39"*.zip, *.log"
is a single string not an array. – Santiago Squarzon Commented Jan 29 at 15:41$exceptions
parameter for-notin
instead of'.zip','.log'
, all files are deleted. I'm thinking @Santiago is correct, and I need to find the correct syntax for specifying an array on the command line. – Hobbes Commented Jan 29 at 15:48-exceptions "*.zip, *.log"
(ie.-exceptions *.zip,*.log
) will do the trick – Mathias R. Jessen Commented Jan 29 at 15:51