powershell - Delete files in a folder except a list of extensions I specify - Stack Overflow

admin2025-04-18  3

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?

Share Improve this question asked Jan 29 at 15:35 HobbesHobbes 2,1553 gold badges20 silver badges39 bronze badges 6
  • Use Get-ChildItem to discover the files to delete, then filter using Where-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
  • @MathiasR.Jessen a quick test shows that that has the same problem: when I specify my $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
  • @Hobbes Yes, you definitely need to pass 2 strings when you're testing for 2 different extensions. Removing the quotation marks from -exceptions "*.zip, *.log" (ie. -exceptions *.zip,*.log) will do the trick – Mathias R. Jessen Commented Jan 29 at 15:51
  • From where do you call the script ? cmd or powershell itself? – Santiago Squarzon Commented Jan 29 at 16:40
 |  Show 1 more comment

2 Answers 2

Reset to default 1

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".

转载请注明原文地址:http://anycun.com/QandA/1744955854a89995.html