16

I have a list of filenames in a text file like this:

f1.txt
f2
f3.jpg

How do I delete everything else from a folder except these files in Powershell?

Pseudo-code:

  • Read the text file line-by-line
  • Create a list of filenames
  • Recurse folder and its subfolders
  • If filename is not in list, delete it.

3 Answers 3

23

Data:

-- begin exclusions.txt --
a.txt
b.txt
c.txt
-- end --

Code:

# read all exclusions into a string array
$exclusions = Get-Content .\exclusions.txt

dir -rec *.* | Where-Object {
   $exclusions -notcontains $_.name } | `
   Remove-Item -WhatIf

Remove the -WhatIf switch if you are happy with your results. -WhatIf shows you what it would do (i.e. it will not delete)

-Oisin

Sign up to request clarification or add additional context in comments.

5 Comments

I like it. Why not use -notcontains, though?
Thanks. This works perfectly for me. I tried with -notcontains as Mike suggested and the results are same.
i hate -notcontains. nah, only kidding. yeah, that's ever terser.
Since the results returned by dir -rec *.* are FileInfo instances, you can just use $_.Name to get the file name. PowerShell converts the file to a string in order to call [io.path]::GetFileName($_).
@EmperorXLII True, that.
6

If the files exist in the current folder then you can do this:

Get-ChildItem -exclude (gc exclusions.txt) | Remove-Item -whatif

This approach assumes each file is on a separate line. If the files exist in subfolders then I would go with Oisin's approach.

2 Comments

Yeah, files are on separate lines. Thanks for the answers. If the parent location has subfolders, I get a prompt saying "The item at Microsoft.PowerShell.Core\FileSystem::<<path>> has children and the Recurse parameter was not specified. If you continue, all children will be removed with the item. Are you sure you want to continue?" Probably adding the -recurse switch will fix it. Oisin's approach doesn't cause this prompt.
If subdirs are involved then you do not want to use my approach and you don't want to use -r otherwise it will delete entire folders.
1

actually this only seems to work for the first directory rather than recursing - my altered script recurses properly.

$exclusions = Get-Content .\exclusions.txt

dir -rec | where-object {-not($exclusions -contains [io.path]::GetFileName($_))} | `  
where-object {-not($_ -is [system.IO.directoryInfo])} | remove-item -whatif

1 Comment

I used $_.FullName.ToLower() instead of [io.path]::GetFileName($_) and used full path names in my exclusion list to get the recursion to work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.