skip to content

del — Delete Files

Delete one or more files from the Windows command prompt. Covers wildcards, quiet mode, attribute overrides, recursive deletion patterns, and the distinction from rmdir.

12 min read 60 snippets deep dive

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#

SwitchMeaning
/PPrompt before deleting each file
/FForce deletion of read-only files
/SDelete from all subdirectories matching the pattern
/QQuiet — no confirmation prompt for wildcards
/ASelect files by attribute; prefix with - to negate
/A:HDelete hidden files
/A:RDelete read-only files
/A:SDelete system files
/A:ADelete 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#

  1. del bypasses 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.
  2. del *.* in a directory deletes files but not the directory itself — use rmdir /S /Q to remove the whole tree.
  3. Wildcards in interactive mode prompt once for the group — a single Y deletes all matched files; there is no per-file chance to review.
  4. Read-only files silently survivedel readonly.txt exits 0 but leaves the file; add /F to actually remove it.
  5. del without a path acts on the current directory — always verify cd output before running del *.* /Q.
  6. /S scans 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#

GoalCMDPowerShellbash (Linux/macOS)
Delete one filedel foo.txtRemove-Item foo.txtrm foo.txt
Force read-onlydel /F foo.txtRemove-Item foo.txt -Forcerm -f foo.txt
Silent / no promptdel /Q *.tmpRemove-Item *.tmp (no prompt by default)rm -f *.tmp
Recursive across subdirsdel /S /Q *.pycGet-ChildItem -Recurse -Filter *.pyc | Remove-Item -Forcefind . -name '*.pyc' -delete
Per-file confirm(not built in; only group prompt)Remove-Item *.tmp -Confirmrm -i *.tmp
Dry run(none built in; use dir)Remove-Item ... -WhatIffind ... -print (or echo rm ...)
Hidden files onlydel /A:H /Q *Get-ChildItem -Hidden -File | Remove-Item -Forcerm .[^.]* (or find . -name '.*')
Older than N daysforfiles /D -30 /C "cmd /c del /Q @path"Get-ChildItem | ? LastWriteTime -lt (Get-Date).AddDays(-30) | Remove-Itemfind . -mtime +30 -delete
Move to trash / safe(Shell COM workaround)Remove-ItemSafely (Recycle module)trash (gio/trash-cli)
Empty file pattern testdel /S /Q "*.bak"Remove-Item *.bak -Recurse -Forcerm -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)#

  1. 8.3 short-name aliases match unexpectedlydel *.htm may delete *.html files. Disable 8.3 generation or use for /R with a regex pre-filter.
  2. del *.* /S from drive root is catastrophic — accidentally running this from C:\ removes most user files. Always verify %CD% and consider set "RM_GUARD=1" style trip-wires.
  3. del exits 0 even when nothing was deleted — wrap with if exist checks or count results with dir /B if the script must know whether anything happened.
  4. System file deletion needs elevationdel /A:S /F /Q C:\Windows\Temp\* will fail without an admin prompt. Use runas or an elevated cmd.
  5. 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.
  6. Junctions and symlinksdel on a symlink-to-file removes the link, not the target. del /S does NOT recurse through junctions to delete target contents (good), but Remove-Item -Recurse in 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.

See also#

  • rmdir / rd — remove empty or whole directory trees; complements del.
  • erase — the alias of del.
  • attrib — clear read-only/hidden/system flags before deleting protected files.
  • forfiles — date-based file selection often paired with del.
  • robocopy /MOV — move-then-delete with retry semantics, safer than del for unstable storage.
  • PowerShell Remove-Item, Remove-ItemSafely — flexible deletion with optional Recycle Bin support.
  • Linux rm, find ... -delete — Unix equivalents.