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 $_}
cmdlet parameters
The Remove-Item and Get-ChildItem cmdlets share several parameters you can use for testing purposes.

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.

Verbose parameter
The Verbose parameter shows the action taken by the command.

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
file share folder structure
Use the Get-ChildItem command to show files stored in multiple subfolders.

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.

Get-ChildItem command
Verify the deletion of files with the Get-ChildItem command.

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
file time and date properties
The PowerShell command gathers the time and date properties attached to a file.

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.

delete files command
Pipe the files that fit the date criteria to the Remove-Item cmdlet to delete the files.

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
WhatIf parameter test
The WhatIf parameter tests the delete command before any files are removed.

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.

Dig Deeper on Windows Server OS and management