PowerShell Delete Files and Folders: Remove-Item Guide

PowerShell Delete Files and Folders: Remove-Item Guide

PowerShell Tips Editor 3 min read
PowerShell Delete Files and Folders: Remove-Item Guide

PowerShell’s Remove-Item can delete files and folders permanently — no Recycle Bin, no confirmation dialog by default. That power demands respect. This guide starts with the most important habit first: always use -WhatIf before deleting anything in a script. Then it covers safe recursive deletion, handling read-only files, bulk deletion by extension, and building confirmation prompts into your cleanup scripts.

Basic Remove-Item Syntax

Delete a single file or folder by path:

# Delete a single file
Remove-Item -Path 'C:\Logs\old.log'

# Aliases: del, rm, ri (all call Remove-Item)
del 'C:\Temp\tempfile.tmp'

# Delete a file and verify it's gone
Remove-Item -Path 'C:\Logs\old.log'
Test-Path 'C:\Logs\old.log'   # Returns False
False

Without -Recurse, Remove-Item will not delete non-empty folders. Without -Force, it won’t delete read-only files. Without -WhatIf, deletion is immediate and permanent.

Deleting Folders Recursively

To delete a folder and everything in it, you must explicitly add -Recurse:

# Delete a folder and all contents — NO WAY TO UNDO
Remove-Item -Path 'C:\Temp\OldBuild' -Recurse

# Delete only the contents, keep the folder itself
Get-ChildItem 'C:\Temp\OldBuild' | Remove-Item -Recurse -Force

# Delete multiple folders at once
Remove-Item 'C:\Temp\Build1', 'C:\Temp\Build2', 'C:\Temp\Build3' -Recurse

Deleting a folder with -Recurse is irreversible. The folder and all files inside — including subfolders and hidden files — are permanently removed. Test with -WhatIf first.

Using -WhatIf to Preview Deletion

The most important habit when writing cleanup scripts: run with -WhatIf first to see exactly what would be deleted:

# Preview deletion without doing anything
Remove-Item -Path 'C:\Logs\*.log' -WhatIf

# Preview recursive deletion
Remove-Item -Path 'C:\Temp\OldLogs' -Recurse -WhatIf

# Preview bulk deletion matching a pattern
Get-ChildItem 'C:\Logs' -Filter '*.tmp' -Recurse |
    Remove-Item -WhatIf
What if: Performing the operation "Remove File" on target "C:\Logs\app.log".
What if: Performing the operation "Remove File" on target "C:\Logs\error.log".
What if: Performing the operation "Remove File" on target "C:\Logs\debug.log".

The output of -WhatIf shows every file that would be deleted. Review the list carefully, then remove the -WhatIf flag to execute. This two-step pattern prevents accidental data loss.

Deleting Read-Only Files with -Force

Files with the read-only attribute set throw an error without -Force:

# Without -Force: fails on read-only files
# Remove-Item 'C:\Logs\readonly.log'  # Error: Access to the path is denied

# With -Force: removes read-only attribute and deletes
Remove-Item -Path 'C:\Logs\readonly.log' -Force

# Delete read-only files in a folder
Get-ChildItem 'C:\Logs' -Filter '*.log' |
    Where-Object { $_.IsReadOnly } |
    Remove-Item -Force

Bulk Delete by Extension

Clean up temporary or log files matching a pattern:

# Delete all .tmp files in a folder
Remove-Item -Path 'C:\Temp\*.tmp'

# Recursive cleanup of .log files older than 30 days
$cutoff = (Get-Date).AddDays(-30)
Get-ChildItem -Path 'C:\Logs' -Filter '*.log' -Recurse -File |
    Where-Object { $_.LastWriteTime -lt $cutoff } |
    Remove-Item -WhatIf   # Remove -WhatIf when ready to run

# Multiple extension types
Get-ChildItem 'C:\Temp' -Recurse -File |
    Where-Object { $_.Extension -in @('.tmp', '.bak', '.temp') } |
    Remove-Item -Force
What if: Performing the operation "Remove File" on target "C:\Logs\app_2026-04-01.log".
What if: Performing the operation "Remove File" on target "C:\Logs\Archive\app_2026-03-15.log".

Safe Deletion with Confirm Prompt

For interactive scripts, add a confirmation step:

# -Confirm prompts before each deletion
Remove-Item 'C:\Logs\*.log' -Confirm

# Build a safer bulk delete with summary first
$filesToDelete = Get-ChildItem 'C:\Logs' -Filter '*.log' -Recurse -File |
    Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-7) }

Write-Output "Found $($filesToDelete.Count) files to delete:"
$filesToDelete | Select-Object FullName, LastWriteTime | Format-Table

$confirm = Read-Host 'Delete these files? (yes/no)'
if ($confirm -eq 'yes') {
    $filesToDelete | Remove-Item -Force
    Write-Output 'Deletion complete'
} else {
    Write-Output 'Cancelled'
}

Common Errors and Fixes

  • Forgetting -Recurse on non-empty folder: Remove-Item 'C:\Folder' on a folder with contents throws “The item at C:\Folder has children and the Recurse parameter was not specified.” Add -Recurse to delete all contents, or empty the folder first.
  • Wildcard deleting more files than intended: Remove-Item 'C:\Logs\*' deletes everything in C:\Logs, including subfolders and files you didn’t intend to touch. Use -Filter '*.log' to restrict the pattern, and always test with -WhatIf first.

Related Cmdlets / See Also

Wrapping Up

Remove-Item permanently deletes files and folders. The two habits that prevent disasters: use -WhatIf before every deletion script, and use specific -Filter patterns rather than broad wildcards. For production cleanup scripts, add a summary and confirmation prompt. Your next step: write a log rotation script that deletes files older than 30 days with a -WhatIf preview mode.

Send-Item -To