Search code examples
powershell

Delete files in a folder except a list of extensions I specify


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?


Solution

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