cheat sheet
del
Delete one or more files from the Windows command prompt. Covers wildcards, quiet mode, attribute overrides, recursive deletion patterns, and the distinction from rmdir.
del — Delete Files
What it is
del (also erase) is a built-in cmd.exe command that permanently deletes one or more files from disk — bypassing the Recycle Bin entirely. It has been present since MS-DOS 1.0. Unlike rmdir, del removes only files, not directories; use rmdir /S to remove an entire folder tree. There is no undo: once deleted with del, files are gone unless a shadow copy or backup exists.
Availability
del is built into cmd.exe on every Windows version. erase is an exact alias. In PowerShell use Remove-Item (aliased del, rm, ri).
del /?
Output:
Deletes one or more files.
DEL [/P] [/F] [/S] [/Q] [/A[[:]attributes]] names
ERASE [/P] [/F] [/S] [/Q] [/A[[:]attributes]] names
Syntax
The target can be a filename, wildcard, or space-separated list of names. Paths containing spaces must be quoted.
del [/P] [/F] [/S] [/Q] [/A[:attributes]] target [target ...]
Output: (none on success; error message if file not found or access denied)
Essential options
| Switch | Meaning |
|---|---|
/P | Prompt before deleting each file |
/F | Force deletion of read-only files |
/S | Delete from all subdirectories matching the pattern |
/Q | Quiet — no confirmation prompt for wildcards |
/A | Select files by attribute; prefix with - to negate |
/A:H | Delete hidden files |
/A:R | Delete read-only files |
/A:S | Delete system files |
/A:A | Delete files with archive bit set |
Deleting a single file
The simplest form deletes one named file. The command is silent on success.
del report_draft.docx
Output: (none — exits 0 on success)
rem Full path
del C:\Temp\installer.msi
Output: (none — exits 0 on success)
rem Path with spaces — must quote
del "C:\Users\alicedev\My Documents\old notes.txt"
Output: (none — exits 0 on success)
Wildcard deletion
Wildcards delete multiple files matching a pattern. When a wildcard matches more than one file, cmd.exe in interactive mode asks for confirmation (one prompt for the whole group, not per file). Use /Q to suppress the prompt.
rem Delete all .tmp files in the current folder
del *.tmp
Output:
C:\Temp\*, Are you sure (Y/N)? Y
rem Silent wildcard delete (scripts should always use /Q)
del /Q *.tmp
Output: (none — exits 0 on success)
rem Delete all log files with a date in the name
del /Q app_2025*.log
Output: (none — exits 0 on success)
Recursive deletion
/S extends the delete to matching files in all subdirectories. Combine with /Q for unattended use. The directory structure is left intact — only the matched files are removed.
rem Delete all .pyc files recursively
del /S /Q *.pyc
Output:
Deleted file - C:\Projects\myapp\__pycache__\main.cpython-312.pyc
Deleted file - C:\Projects\myapp\__pycache__\utils.cpython-312.pyc
rem Delete all .log files under a logs folder
del /S /Q C:\Logs\*.log
Output:
Deleted file - C:\Logs\app.log
Deleted file - C:\Logs\Archive\app.log
Force-deleting read-only files
del fails silently on read-only files unless /F is specified. Combine with /Q for scripts.
rem Will fail silently if file is read-only
del locked.txt
rem Force deletion regardless of read-only attribute
del /F locked.txt
Output: (none — exits 0 on success with /F)
rem Force-delete all read-only .bak files recursively
del /F /S /Q *.bak
Output: (none — exits 0 on success)
Attribute-targeted deletion
/A selects files by attribute flag — useful for cleaning hidden temp files or targeting only archived files.
rem Delete only hidden files in current folder
del /A:H /Q *
Output: (none — exits 0 on success)
rem Delete files with archive bit set (post-backup cleanup)
del /A:A /Q C:\Exports\*.csv
Output: (none — exits 0 on success)
rem Delete system files (use with care; requires elevation)
del /A:S /F /Q C:\Quarantine\*
Output: (none — exits 0 on success)
Deleting all files in a folder
del * or del /Q /S * clears every file; combine with rmdir afterward to remove the directory itself if desired.
rem Clear all files in a temp folder (not the folder itself)
del /Q /F C:\Temp\*
Output: (none — exits 0 on success)
rem Clear all files recursively, force read-only
del /Q /F /S C:\OldProject\*
Output: (none — exits 0 on success)
Common pitfalls
delbypasses the Recycle Bin — files are gone immediately; use the Explorer Delete key or PowerShell with the Shell COM object if you want Recycle Bin behaviour.del *.*in a directory deletes files but not the directory itself — usermdir /S /Qto remove the whole tree.- Wildcards in interactive mode prompt once for the group — a single
Ydeletes all matched files; there is no per-file chance to review. - Read-only files silently survive —
del readonly.txtexits 0 but leaves the file; add/Fto actually remove it. delwithout a path acts on the current directory — always verifycdoutput before runningdel *.* /Q./Sscans all subdirectories — ensure your wildcard is specific enough before adding/S /Q.
Real-world recipes
Clean all build artefacts before a fresh build
del /S /Q /F *.pyc *.pyo
del /S /Q /F *.obj *.pdb *.ilk
Output: (none — exits 0 on success)
Delete files older than 30 days with forfiles
forfiles /P C:\Logs /S /M *.log /D -30 /C "cmd /c del /Q @path"
Output: (none — exits 0 on success)
Wipe temp folder
del /Q /F /S %TEMP%\*
Output: (none — exits 0 on success)
Prompt-safe delete in a batch script
@echo off
echo About to delete all .tmp files in C:\Scratch
echo Press Ctrl+C to abort or any key to continue...
pause > NUL
del /Q /F C:\Scratch\*.tmp
echo Done.
Output:
About to delete all .tmp files in C:\Scratch
Press Ctrl+C to abort or any key to continue...
Done.
erase — the alias
erase is exactly the same command as del. There is no functional difference; the alias exists for MS-DOS 1.0 compatibility when both ERASE (the IBM PC-DOS spelling) and DEL (the Microsoft preference) were shipped. Scripts may use either, but del is by far the more common form in modern documentation.
erase /Q C:\Temp\*.tmp
Output: (none — exits 0 on success)
Wildcards and pattern semantics
del uses the legacy DOS wildcard engine inherited by cmd.exe. * matches any sequence including the empty string; ? matches exactly one character. Two crucial quirks to remember: *.* historically meant "files with any extension" but on modern Windows it matches all files including those without an extension, and a single * is equivalent to *.*. Also, pattern matching considers both the long filename and the legacy 8.3 short name, so del *.htm may unexpectedly delete *.html files because their 8.3 alias ends in .HTM.
rem * and *.* both match every file
del *
del *.*
Output:
C:\Temp\*, Are you sure (Y/N)?
rem 8.3 surprise: deletes both report.htm AND report.html
dir /B
del *.htm
dir /B
Output:
report.htm
report.html
notes.txt
notes.txt
rem Disable 8.3 matching to avoid the surprise (PowerShell or attrib /L; see fsutil)
fsutil 8dot3name set 1
Output:
The registry state is now: 1 (Disable 8dot3 name creation on all volumes).
Exit codes and error behaviour
del returns 0 even when no files matched the pattern — which differs from most Unix utilities. To detect "did anything actually get deleted?" use dir to check beforehand or capture output. Errors during deletion (access denied, file in use) print a message but typically still return 0 unless the entire invocation failed.
rem No matches — exits 0 with "Could Not Find" message
del C:\Temp\does_not_exist*.tmp
echo Exit code: %ERRORLEVEL%
Output:
Could Not Find C:\Temp\does_not_exist*.tmp
Exit code: 0
rem Explicit check before delete
if exist C:\Temp\*.tmp (del /Q /F C:\Temp\*.tmp) else (echo Nothing to delete)
Output:
Nothing to delete
Recycle Bin behaviour and recovery
del, erase, and rmdir all bypass the Windows Recycle Bin completely. Files removed with these commands are not in any user-accessible trash and recovering them requires forensic tools, shadow copies (vssadmin list shadows), or File History snapshots. PowerShell's Remove-Item also bypasses the Recycle Bin by default. To delete to the Recycle Bin from a script, invoke the Shell COM object.
# Delete-to-recycle-bin via Shell COM (closest "safe delete")
$file = "C:\Temp\important.txt"
$shell = New-Object -ComObject Shell.Application
$item = $shell.Namespace((Split-Path $file)).ParseName((Split-Path $file -Leaf))
$item.InvokeVerb("delete")
Output: (none — file goes to Recycle Bin)
# The Recycle module from PSGallery exposes Remove-ItemSafely
Install-Module -Name Recycle -Scope CurrentUser
Remove-ItemSafely C:\Temp\important.txt
Output: (none — file recyclable from Bin)
PowerShell equivalents
Remove-Item (aliases del, erase, rm, ri, rmdir, rd) is the PowerShell native. It is dramatically more flexible than del: pipeline input, -Recurse, -Force, -Include/-Exclude, -WhatIf, -Confirm, -Filter, and provider-aware behaviour for registry, certificate, and other non-filesystem stores. PowerShell's del is not the cmd builtin — it is Remove-Item with PowerShell semantics, which means flags like /Q and /F do nothing in PowerShell.
# Single file
Remove-Item C:\Temp\report.docx
Output: (none — silent success)
# Force removal of read-only file (equivalent of del /F)
Remove-Item C:\Temp\locked.txt -Force
Output: (none — silent success)
# Wildcard
Remove-Item C:\Logs\*.log
Output: (none — silent success)
# Recursive across subdirectories (equivalent of del /S)
Get-ChildItem C:\Projects\myapp -Recurse -Filter *.pyc | Remove-Item -Force
Output: (none — silent success)
# Hidden files only
Get-ChildItem C:\Temp -Hidden -File | Remove-Item -Force
Output: (none — silent success)
# Files older than 30 days
$cutoff = (Get-Date).AddDays(-30)
Get-ChildItem C:\Logs -File |
Where-Object LastWriteTime -lt $cutoff |
Remove-Item -Force
Output: (none — silent success)
# Dry run with -WhatIf before committing
Remove-Item C:\Temp\* -Recurse -Force -WhatIf
Output:
What if: Performing the operation "Remove File" on target "C:\Temp\a.txt".
What if: Performing the operation "Remove File" on target "C:\Temp\b.tmp".
# Interactive per-item confirmation
Remove-Item C:\Temp\*.tmp -Confirm
Output:
Confirm
Are you sure you want to perform this action?
Performing the operation "Remove File" on target "C:\Temp\a.tmp".
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"):
CMD vs PowerShell vs bash comparison
| Goal | CMD | PowerShell | bash (Linux/macOS) |
|---|---|---|---|
| Delete one file | del foo.txt | Remove-Item foo.txt | rm foo.txt |
| Force read-only | del /F foo.txt | Remove-Item foo.txt -Force | rm -f foo.txt |
| Silent / no prompt | del /Q *.tmp | Remove-Item *.tmp (no prompt by default) | rm -f *.tmp |
| Recursive across subdirs | del /S /Q *.pyc | Get-ChildItem -Recurse -Filter *.pyc | Remove-Item -Force | find . -name '*.pyc' -delete |
| Per-file confirm | (not built in; only group prompt) | Remove-Item *.tmp -Confirm | rm -i *.tmp |
| Dry run | (none built in; use dir) | Remove-Item ... -WhatIf | find ... -print (or echo rm ...) |
| Hidden files only | del /A:H /Q * | Get-ChildItem -Hidden -File | Remove-Item -Force | rm .[^.]* (or find . -name '.*') |
| Older than N days | forfiles /D -30 /C "cmd /c del /Q @path" | Get-ChildItem | ? LastWriteTime -lt (Get-Date).AddDays(-30) | Remove-Item | find . -mtime +30 -delete |
| Move to trash / safe | (Shell COM workaround) | Remove-ItemSafely (Recycle module) | trash (gio/trash-cli) |
| Empty file pattern test | del /S /Q "*.bak" | Remove-Item *.bak -Recurse -Force | rm -f **/*.bak (with shopt -s globstar) |
Long path support
del and del /S honour LongPathsEnabled on Windows 10 1607+ but the implementation is uneven — some inner code paths still hit MAX_PATH. For deeply nested trees, PowerShell's Remove-Item -LiteralPath '\\?\C:\very\long\path' or robocopy /MIR from an empty source are more reliable than del /S.
rem When del /S fails on long paths
robocopy emptydir C:\too\long\path /MIR /R:1 /W:1 /NFL /NDL /NJH /NJS
rmdir C:\too\long\path
Output:
Files : 500 0 0 0 0 500
Common pitfalls (continued)
- 8.3 short-name aliases match unexpectedly —
del *.htmmay delete*.htmlfiles. Disable 8.3 generation or usefor /Rwith a regex pre-filter. del *.* /Sfrom drive root is catastrophic — accidentally running this fromC:\removes most user files. Always verify%CD%and considerset "RM_GUARD=1"style trip-wires.delexits 0 even when nothing was deleted — wrap withif existchecks or count results withdir /Bif the script must know whether anything happened.- System file deletion needs elevation —
del /A:S /F /Q C:\Windows\Temp\*will fail without an admin prompt. Userunasor an elevated cmd. - OneDrive and cloud sync — files on a OneDrive cloud-only placeholder are downloaded before deletion, which can take time and trigger reflow events. Disable sync first for bulk deletes.
- Junctions and symlinks —
delon a symlink-to-file removes the link, not the target.del /Sdoes NOT recurse through junctions to delete target contents (good), butRemove-Item -Recursein older PowerShell versions did (use 7+).
Real-world recipes (continued)
Atomic "trash" workaround using move
If you cannot afford permanent deletion, move files to a date-stamped trash folder and prune the trash periodically. This gives you an undo window.
@echo off
setlocal EnableExtensions
set TRASH=C:\Trash\%DATE:~-4,4%%DATE:~-10,2%%DATE:~-7,2%
if not exist "%TRASH%" mkdir "%TRASH%"
move /Y "%~1" "%TRASH%\"
endlocal
Output: (none — file moved to dated trash folder)
Delete only files that haven't been accessed in 90 days
forfiles /P C:\Cache /S /M *.* /D -90 /C "cmd /c if @isdir==FALSE del /Q @path"
Output: (none — exits 0 on success)
Selective purge with size threshold
rem Find and delete files over 100MB
for /R C:\Downloads %f in (*.iso *.zip) do (
for /F %s in ('powershell -NoProfile -Command "(Get-Item '%f').Length"') do (
if %s GTR 104857600 del /F /Q "%f"
)
)
Output: (none — exits 0 on success)
Wipe a directory recursively, leaving structure intact
rem Empty all files but keep folder hierarchy
del /Q /F /S C:\Scratch\*
Output:
Deleted file - C:\Scratch\a.txt
Deleted file - C:\Scratch\sub\b.txt
PowerShell: parallel delete with throttling (PS7+)
Get-ChildItem C:\Logs -Recurse -File -Filter *.log |
ForEach-Object -Parallel { Remove-Item $_ -Force } -ThrottleLimit 8
Output: (none — silent success)
Audit-friendly delete with log file
@echo off
set LOG=C:\Logs\del_audit_%DATE:~-4,4%%DATE:~-10,2%%DATE:~-7,2%.log
dir /B /S C:\Scratch\*.tmp > "%LOG%"
del /Q /F /S C:\Scratch\*.tmp >> "%LOG%" 2>&1
echo Audit log: %LOG%
Output:
Audit log: C:\Logs\del_audit_20260525.log
Sources
References consulted while writing this article. Links open in a new tab.
- Microsoft Learn — del command reference — Authoritative flag list and parameter semantics used to build the Essential options table.
- SS64 — del — Cross-version comparison and historical syntax notes.
See also
rmdir/rd— remove empty or whole directory trees; complementsdel.erase— the alias ofdel.attrib— clear read-only/hidden/system flags before deleting protected files.forfiles— date-based file selection often paired withdel.robocopy /MOV— move-then-delete with retry semantics, safer thandelfor unstable storage.- PowerShell
Remove-Item,Remove-ItemSafely— flexible deletion with optional Recycle Bin support. - Linux
rm,find ... -delete— Unix equivalents.