How to Delete Temporary Files in Windows Using CMD

Jump to

Deleting temporary files hardly ranks as a glamorous task, yet it sits at the center of predictable, automated, low-latency build and deployment pipelines. On a local workstation the stakes are modest: you reclaim some disk space. On a self-hosted agent pool or a fleet of short-lived Windows containers, the same habit protects against job failures triggered by full volumes, sluggish I/O, and unrepeatable test runs. This article shows, in plain terms, how to clear Windows temporary directories from the command line and how to fold that process into a DevOps workflow without drama.

CMD

(Credits)

Why CMD still matters

PowerShell dominates modern Windows scripting, but the classic Command Prompt (cmd.exe) remains relevant.

  • It is present on every supported Windows image, server or client.
  • Many third-party build tools (e.g., msbuild, legacy installers, or vendor batch files) still spawn child cmd.exe sessions.
  • Some CI/CD platforms default to cmd.exe for bootstrap scripts unless you override the shell.

Therefore, knowing how to wield del, forfiles, and rd is useful even if your favorite shell is PowerShell, Bash, or zsh.

What counts as a “temporary file”

Windows tracks two environment variables:

shell

%TEMP%%TMP%

Both expand to the current user’s temp folder, typically

pgsql

C:\Users\<UserName>\AppData\Local\Temp

When a process runs under the SYSTEM account or within a service context, %TEMP% resolves to

makefile

C:\Windows\Temp

Other locations also generate throwaway data—browser caches, Windows Update remnants, log folders—but %TEMP% captures the bulk of disposable files created by compilers, package managers, and test harnesses during CI jobs. Focus there first before widening the net.

Inspect before you delete

A DevOps pipeline should not blindly erase data. Verify what you intend to remove. Use the following read-only commands:

cmd

echo %TEMP%dir /a /s %TEMP%

/a lists all files including system and hidden; /s traverses subdirectories. Capture the total size with:

cmd

dir /a /s %TEMP% | find "File(s)"

When this number grows past a threshold you set (for example, 2 GB on a 10 GB container layer or 5 GB on a bare-metal build agent), schedule a cleanup job.

Simple ad-hoc deletion

The most direct approach is a two-liner.

cmd

cd /d %TEMP%del /f /s /q *.* 2>nul

Explanation

  • cd /d changes both drive and directory.
  • del removes files.
    • /f forces deletion of read-only files.
    • /s includes all subfolders.
    • /q runs quietly.
  • 2>nul suppresses “file in use” and “access denied” messages that would otherwise clutter logs.

If you also want to remove now-empty subdirectories:

cmd

for /d %%G in (*) do rd /s /q "%%G" 2>nul

The for loop iterates through each folder and calls rd (remove directory). Place both snippets in a batch file (clean_temp.bat) to standardize local and remote runs.

Selective deletion by age

Build agents often run multiple jobs each hour. Deleting everything after every run wastes I/O cycles and can hide permission issues. Instead, clear only artifacts older than an age threshold.

cmd

forfiles /p "%TEMP%" /s /d -3 /c "cmd /c del /q @path"
forfiles /p "%TEMP%" /s /d -3 /c "cmd /c if @isdir==TRUE rd /s /q @path"
  • /p sets the root path.
  • /d -3 means “modified three or more days ago.”
  • @isdir tests whether the current object is a directory.

Adjust the number to fit your usage pattern—-1 for nightly scrubs, -7 for weekly.

Elevation and service accounts

A local developer who runs cmd.exe as standard user can delete only files that her account owns. A release pipeline agent, however, usually runs under NT AUTHORITY\SYSTEM or a custom service identity with broad rights. Where required, wrap the script in a helper that launches an elevated shell:

cmd

powershell -Command "Start-Process cmd -ArgumentList '/c clean_temp.bat' -Verb RunAs"

In a CI runner this step is unnecessary because the agent service is already privileged, but on interactive test VMs it eliminates manual clicks.

Automating with Scheduled Tasks

Long-lived build servers accumulate junk even when individual pipelines finish with clean_temp.bat. Add a maintenance task:

cmd

schtasks /Create ^
  /SC DAILY ^
  /TN "TempCleanup" ^
  /TR "cmd.exe /c C:\Scripts\clean_temp.bat" ^
  /ST 02:00 ^
  /RU "SYSTEM"

This example sets a 2 AM daily run under the SYSTEM account. For transient Azure DevOps or GitHub Actions agents you can skip scheduling because the VM usually self-deletes; nonetheless, including the cleanup step in the pipeline ensures disk hygiene if retention settings change.

Integrating into a pipeline

Azure DevOps YAML

yaml

steps:
- powershell: |
    write-host "Cleaning %TEMP% on $(computerName)"
    cmd /c clean_temp.bat
  displayName: Remove temp files

GitHub Actions

yaml

- name: Remove temp files
  run: cmd /c clean_temp.bat
  shell: cmd

Because the cmd shell does not natively propagate non-zero exit codes from del when some files are locked, the script ends with:

cmd

exit /b 0

This avoids a red pipeline status when residual handles exist (for example, Visual Studio telemetry files). If you prefer strict failure detection, omit that line and let the job fail when del returns 5 (“access is denied”).

Cleaning Windows containers

Docker images that host .NET build stages often layer tens of thousands of compiler temp files into the UnionFS cache. Keep image size predictable:

dockerfile

RUN cmd /c clean_temp.bat & \
    dism.exe /online /Cleanup-Image /StartComponentCleanup /ResetBase

The dism line consolidates component store layers, further trimming space. Remember to copy clean_temp.bat into the container during the earlier COPY step or bake it into a base image common to all pipelines.

Mitigating “file in use” issues

Even after a cleanup run, some files stubbornly remain because another process holds a handle. Typical culprits:

  • Anti-virus scanners
  • Continuous logging agents
  • Long-running GUI apps left open on a build jump box

Three strategies help:

  1. Kill non-essential processes before deletion. For example:

cmd

taskkill /im myTool.exe /f 2>nul
  1. Retry deletes in a loop. A simple exponential back-off reduces noise:

cmd

set RETRIES=3
:retry
del /f /s /q "%TEMP%\*.*" 2>nul
if errorlevel 1 if %RETRIES% gtr 0 (
    timeout /t 5 >nul
    set /a RETRIES-=1
    goto retry
)
  1. Reboot and clean at startup. For bare-metal CI hosts, schedule the batch file with the At startup trigger in Task Scheduler. The boot sequence runs before long-lived user processes start, so file locks vanish.

Logging and metrics

Disk hygiene should be observable. Send cleanup stats to your telemetry stack so you can correlate disk savings with pipeline duration.

cmd

for /f "tokens=3" %%S in ('dir /a /s %TEMP% ^| find "File(s)"') do set SPACE=%%S
echo { "tempSizeBefore": "%SPACE%", "host": "%COMPUTERNAME%", "timestamp": "%DATE% %TIME%" } >> C:\Logs\temp_cleanup.json

A lightweight sidecar (Fluent Bit, for instance) can tail the JSON file and flush the metrics to Elasticsearch, Loki, or CloudWatch. Patterns worth alerting on:

  • Cleanup freed less than 50 MB (indicates nothing to delete, maybe the job skipped).
  • Cleanup freed more than 5 GB (signals an underlying build-artifact leak).
  • Error codes other than 0 or 5.

Hardening the script

Treat a temp scrubber like any other production artifact:

  1. Version-control it. Store clean_temp.bat alongside other pipeline utilities.
  2. Code-review changes. Deleting files is destructive; peer approval prevents typos such as cd /d C:\ before del /f /s /q *.*.
  3. Pin paths. Use explicit variables (%TEMP%) instead of C:\Temp literals so the script respects redirected folders.
  4. Add dry-run mode. A SET DRYRUN=1 flag that switches del to echo del… lets operators validate scope during incident response.

Common pitfalls

PitfallStatusFix
Running as a non-admin service accountFiles remainUse NT AUTHORITY\SYSTEM or elevate with RunAs
Access is denied to %Windir%\TempBuilt-in protectionsExclude that directory or take ownership (takeown /F …)
Batch file returns exit code 2 (file not found)HarmlessMask in CI with exit /b 0 or ignore in error handler
Clean step dramatically slows the jobPossibly huge directoryTune /d -N threshold or run scrub only on weekends

Putting it all together

Below is a consolidated batch file that balances safety and completeness. Save it as clean_temp.bat:

cmd

@echo off
setlocal enabledelayedexpansion

rem -----------------------------
rem  Configuration
rem -----------------------------
set DAYS=3
set DRYRUN=0           rem set to 1 for a non-destructive trial
set LOG=C:\Logs\temp_cleanup.log

rem -----------------------------
rem  Functions
rem -----------------------------
:log
echo %DATE% %TIME%  %~1 >> "%LOG%"
goto :eof

rem -----------------------------
rem  Execution
rem -----------------------------
call :log "Starting cleanup. DRYRUN=%DRYRUN%, DAYS=%DAYS%."
for /f "tokens=3" %%S in ('dir /a /s "%TEMP%" ^| find "File(s)"') do set BEFORE=%%S

rem Delete files
if "%DRYRUN%"=="0" (
    forfiles /p "%TEMP%" /s /d -%DAYS% /c "cmd /c del /f /q @path" 2>nul
    forfiles /p "%TEMP%" /s /d -%DAYS% /c "cmd /c if @isdir==TRUE rd /s /q @path" 2>nul
) else (
    forfiles /p "%TEMP%" /s /d -%DAYS% /c "cmd /c echo DRYRUN would del @path"
)

rem Measure result
for /f "tokens=3" %%S in ('dir /a /s "%TEMP%" ^| find "File(s)"') do set AFTER=%%S

call :log "Disk before: %BEFORE%. Disk after: %AFTER%."
exit /b 0
  • Configuration block sits at the top; adjusting DAYS is trivial.
  • With DRYRUN=1 the script only logs intended actions.
  • Metrics record before/after totals so you can chart reclaimed space over time.

Wrap Up

A temporary-file purge is not glamorous, but it reduces noise—disk-full errors, flaky tests, invisible gigabytes baked into container layers—that erode confidence in automated delivery. By mastering a handful of plain cmd.exe instructions (del, forfiles, rd) and embedding them in CI bootstrap, scheduled tasks, and container builds, you ensure every Windows host in your DevOps chain starts light and stays that way. The approach is repeatable, transparent, and almost as fast to execute as it is to read.

Leave a Comment

Your email address will not be published. Required fields are marked *

You may also like

What is WinGet?

What Is WinGet?

WinGet is the command-line client for Windows Package Manager. It installs, upgrades, removes, and configures applications on Windows 10, Windows 11, and Windows Server 2025. By typing a short command

Categories
Scroll to Top