Last Update: Sep 04, 2024 | Published: Jan 14, 2015
Managing files and folders is a never ending task, where I frequently see a common question on how to delete empty folders. Actually deleting a folder is very easy in PowerShell. The real question is how do I identify empty folders?
Let’s take a look. First, we’ll assume you are searching for folders from a given root.
$root = "C:Work"
Beginning with PowerShell 3.0, you can easily filter files or folders. This will get all of the root or top-level folders.
dir $root -Directory
Or I can get all directories.
dir $root –Directory –recurse | Select Fullname
Now that I know the directories, all I need to do is find directories that contain files. I am going to assume that if a folder contains an empty subfolder, then both can be deleted. The easy way to identify if a folder contains a file is to list files. A folder object has a GetFiles() method. If the method returns any files, I can interpret that as True.
dir $root -Directory -recurse | where { $_.GetFiles()} | Select Fullname
Thus, these folders are not empty.
To turn this around all I need to do is use the –Not operator.
dir $root -Directory -recurse | where { -NOT $_.GetFiles()} | Select Fullname
But there is a challenge here. Look at the Demo2 subfolder.
There is an empty subfolder Demo4, but Demo3 contains a file. There are also no files in the root of Demo2. I can’t delete Demo2 because that will remove Demo3 and the file. But I do want to remove Demo4.
This won’t be apparent to you, but let’s revisit the GetFiles() method I used to identify folders with files. This is a .NET method and often there are several ways to invoke methods.
(get-item $root).getfiles.OverloadDefinitions
The SearchOption looks promising. I’m guessing it is a way to telling PowerShell how far to search. In my experience a value like this is an enumeration.
[enum]::GetValues([system.io.searchoption])
This probably means that I can search for a file recursively.
dir $root -Directory -recurse | where { $_.GetFiles("*","AllDirectories")} | Select Fullname
And sure enough, these are the folders that contain at least one file somewhere in the path.
These are files I do not want to remove. So adding –NOT should give a list of truly empty folders.
dir $root -Directory -recurse | where {-NOT $_.GetFiles("*","AllDirectories")} | Select Fullname
I can verify by attempting to get a directory listing of these files.
dir $root -Directory -recurse | where {-NOT $_.GetFiles("*","AllDirectories")} | dir
But all I get is the directory entry.
These folders should be safe to remove.
dir $root -Directory -recurse | where {-NOT $_.GetFiles("*","AllDirectories")} | del -recurse -whatif
I’m using –recurse because some of the folders contain a hierarchy of empty folders. If I didn’t include –Recurse PowerShell would prompt me. I can run the command without –Whatif and all of the empty folders are removed.
Even though I was testing this locally, you should be able to use the same techniques on a remote computer as well. You should be able to use remoting. First, you might want to identify empty folders.
invoke-command -scriptblock { dir c:shared -Directory -recurse | where {-NOT $_.GetFiles("*","AllDirectories")} | Select Fullname} -ComputerName CHI-FP02
I’m using the same command except it is running in a remote session on CHI-FP02.
All I need to do is delete the folders when I’m ready.
invoke-command -scriptblock { dir c:shared -Directory -recurse | where {-NOT $_.GetFiles("*","AllDirectories")} | del -recurse -whatif } -ComputerName CHI-FP02
If you find this is going to be a common task, you might turn all of this into a function. Just be sure to include SupportsShouldProcess so that you can use –Whatif.
So the next time you come across a PowerShell problem to solve, take a step back and consider what the real challenge might be. If you get stuck, I encourage you to use the PowerShell forum on the site.