kentoh - Fotolia
Avoid data overflows with PowerShell Remove-Item
The cmdlet helps delete misplaced files and outdated documents, but you should tune the code to optimize execution and avoid errors when the work entails many files and folders.
When it's time to tidy up your file shares, PowerShell is just the tool for those heavy-duty data spills.
Managing files from the command line often seems counterintuitive. On Windows, the File Explorer is quite comprehensive and user-friendly, so it is natural to avoid PowerShell in favor of File Explorer's convenience.
However, you will find certain data management jobs, such as filtering and bulk deletions, can be clumsy with the GUI tool. The following examples will highlight some of the advantages PowerShell offers when you need to delete files.
How to test the Remove-Item cmdlet
In PowerShell, both Windows PowerShell 5.1 and PowerShell 7, you use the Remove-Item cmdlet to delete files. Remove-Item is destructive, so it's important to test before you execute the command.
For this, you will use another file-management cmdlet: Get-ChildItem. Because these cmdlets share many common parameters, you can use it to test basic Remove-Item commands. To see the shared parameters, run the command:
(Get-Help Remove-Item).parameters.parameter.name | ?{(Get-Help Get-ChildItem).parameters.parameter.name -contains $_}
By using the common parameters, you can test your file deletion commands with Get-ChildItem without worrying about accidentally removing files.
Perform a basic file deletion
The most basic way to use Remove-Item is to specify the fully qualified path to a single file or folder with the Path parameter. As the cmdlet name indicates, the following command will remove the item:
Remove-Item -Path C:\tmp\test.txt
If there are no problems, this action will not produce any output.
To get a better understanding of the command, run it again but with the Verbose parameter, as shown below.
The additional output described the file removal. You can verify the deletion with the Get-Item command, which will generate a "cannot find path" error to indicate the file no longer exists:
Get-Item -Path C:\tmp\test.txt
How to remove files without touching folders
To remove files within a folder structure without deleting the folders, you can do this with the PowerShell pipeline and Remove-Item.
In this example scenario, a department in your company made a mistake with the photos it put in a file-share folder named Events and it needs to remove them while keeping the directories intact. This following command displays the simple file structure:
Get-ChildItem -Recurse
The Recurse parameter tells PowerShell to run the cmdlet for the main folder and all its subfolders. The Remove-Item cmdlet also uses the Recurse parameter; if you apply it, the cmdlet will remove the files and the folders. To limit the command to just files, use the File parameter on Get-ChildItem, as shown in the following command, on the file share:
Get-ChildItem -Recurse -File
To remove those files, pipe the command to the Remove-Item cmdlet. If it runs without issue, there will be no output:
Get-ChildItem -Recurse -File | Remove-Item
To verify the command worked as expected, run the previous Get-ChildItem command again.
Neither command had any output, which is what we wanted.
How to remove files older than a certain date
It is easier to find old files with PowerShell, rather than the File Explorer. In a similar fashion to the previous example, start by retrieving the files with Get-ChildItem and then filtering them with Where-Object before piping to Remove-Item.
There are several properties that contribute to the age of a file. You can see them all by running the following command:
(Get-Item .\testfile.txt).psobject.Properties | ?{$_.TypeNameOfValue -eq 'System.DateTime'} | Select Name,Value
There are good reasons to use any one of these values, but this example will focus on the LastWriteTime property.
In this example, the system I use has a driver that writes logs to the ProgramData directory. You can remove the clutter of these log files with Remove-Item after filtering for files that have not been modified for at least a month with Where-Object:
Get-ChildItem *.log | Where-Object {$_.LastWriteTime -lt (Get-Date).AddDays(-30)}
The command does not use Remove-Item because I want to know what would be removed first. When piping from Get-ChildItem, you can either skip the Remove-Item cmdlet or you can use the WhatIf parameter on Remove-Item.
When you are certain these are the files you want to remove, pipe everything to Remove-Item and use the Verbose parameter to generate some output. For some folders, such as this one, you need to launch PowerShell with elevated rights; otherwise, you will get access errors when you run the command.
Verify PowerShell removed the files by running the earlier Get-ChildItem command:
Get-ChildItem *.log | Where-Object {$_.LastWriteTime -lt (Get-Date).AddDays(-30)}
PowerShell will return no output because the files no longer exist.
How to use a filter with the Remove-Item cmdlet
The previous example used Where-Object to filter items by last modified date. However, another option is the Filter parameter on the Remove-Item cmdlet. We removed .log files in the previous example, but the driver that generates these files also produces backup logs in a .log_backup1 file format. The following example will find these files with the Filter parameter using *.log_backup1 that you can test before any action is taken with the WhatIf parameter.
Remove-Item -Path * -Filter *.log_backup1 -WhatIf
Review the output to be sure the files you want to remove are listed. Once you have verified the filtering is correct, run the same command without the WhatIf parameter to remove the files:
Remove-Item -Path * -Filter *.log_backup1
No output is returned, but you can run Get-ChildItem with the same parameters to verify the files no longer exist:
Get-ChildItem -Path * -Filter *.log_backup1
Use a combination of cmdlets to expand your options
There is more to deleting files in PowerShell than just running the Remove-Item cmdlet. You can use Remove-Item alone to do some simple file-type filtering. When that isn't enough, you can combine Get-ChildItem and Where-Object to target the intended files before you pipe them to Remove-Item. This flexibility is what makes PowerShell such a powerful tool.