How to Clean Build Output Directories Before a New Build in Batch Script
Cleaning build output directories before starting a new build ensures that stale files from previous compilations do not contaminate the new build. Leftover object files, cached assets, or previously generated artifacts can cause subtle and hard-to-diagnose bugs where the build appears to succeed but contains outdated code. A clean build script removes all generated output, caches, and temporary files, guaranteeing that the next build is produced entirely from the current source code.
In this guide, we will explore how to clean build output directories from a Batch Script for various project types and build systems.
Method 1: Basic Output Directory Cleanup
@echo off
setlocal enabledelayedexpansion
echo =============================================
echo BUILD CLEANUP
echo =============================================
echo.
set "dirs=bin obj dist build publish artifacts"
set "cleaned=0"
for %%D in (%dirs%) do (
if exist "%%D\" (
echo Cleaning %%D...
rmdir /s /q "%%D"
if exist "%%D\" (
echo [WARNING] Could not fully remove %%D (files may be locked^)
) else (
echo [OK] Removed.
set /a cleaned+=1
)
)
)
echo.
echo [DONE] Removed !cleaned! directories.
pause
Method 2: Recursive Cleanup (Solution-Wide)
Clean all bin and obj directories throughout a solution:
@echo off
setlocal enabledelayedexpansion
set "root=%~dp0"
set "targets=bin obj"
echo =============================================
echo RECURSIVE BUILD CLEANUP
echo Root: %root%
echo =============================================
echo.
set "cleaned=0"
for %%T in (%targets%) do (
echo Searching for %%T directories...
for /f "delims=" %%D in ('dir /b /s /ad "%root%%%T" 2^>nul') do (
echo Removing: %%D
rmdir /s /q "%%D" 2>nul
if not exist "%%D\" set /a cleaned+=1
)
)
echo.
echo [DONE] Removed !cleaned! directories.
pause
Method 3: Framework-Specific Cleanup
.NET Projects
@echo off
setlocal enabledelayedexpansion
echo Cleaning .NET project...
echo.
:: Use dotnet clean
dotnet clean -v quiet
if %errorlevel%==0 (
echo [OK] dotnet clean
) else (
echo [WARNING] dotnet clean reported issues
)
:: Remove additional directories
set "dirs=bin obj publish artifacts TestResults"
set "cleaned=0"
for %%D in (%dirs%) do (
for /f "delims=" %%P in ('dir /b /s /ad "%%D" 2^>nul') do (
rmdir /s /q "%%P" 2>nul
if not exist "%%P\" set /a cleaned+=1
)
)
echo [OK] Removed !cleaned! bin/obj directories
:: Clean NuGet cache (optional)
:: dotnet nuget locals all --clear
echo [DONE]
pause
Node.js Projects
@echo off
setlocal enabledelayedexpansion
echo Cleaning Node.js project...
echo.
:: Remove build output
set "node_dirs=dist build .next .nuxt"
for %%D in (%node_dirs%) do (
if exist "%%D\" (
rmdir /s /q "%%D"
echo [OK] %%D
)
)
:: Remove node_modules (optional, for full clean)
set /p "full_clean=Also remove node_modules? (Y/N): "
if /i "!full_clean!"=="Y" (
if exist "node_modules\" (
echo Removing node_modules (this may take a moment^)...
rmdir /s /q "node_modules"
echo [OK] node_modules removed
)
)
:: Remove cache directories
for %%D in (.cache .parcel-cache) do (
if exist "%%D\" (
rmdir /s /q "%%D"
echo [OK] %%D
)
)
echo.
echo [DONE]
pause
Java Projects (Maven and Gradle)
@echo off
setlocal
echo Cleaning Java project...
echo.
:: Maven
if exist "pom.xml" (
echo Running Maven clean...
call mvn clean -q
if %errorlevel%==0 (
echo [OK] Maven clean
) else (
echo [WARNING] Maven clean reported issues
)
)
:: Gradle
if exist "build.gradle" (
echo Running Gradle clean...
if exist "gradlew.bat" (
call gradlew.bat clean -q
) else (
call gradle clean -q
)
if %errorlevel%==0 (
echo [OK] Gradle clean
) else (
echo [WARNING] Gradle clean reported issues
)
)
:: Manual cleanup of any remaining directories
for %%D in (target build out) do (
if exist "%%D\" (
rmdir /s /q "%%D"
echo [OK] %%D
)
)
echo.
echo [DONE]
pause
C/C++ Projects
@echo off
setlocal enabledelayedexpansion
echo Cleaning C/C++ project...
echo.
:: Remove object files and executables
set "patterns=*.obj *.o *.exe *.dll *.lib *.pdb *.ilk *.exp *.pch"
set "deleted=0"
for %%P in (%patterns%) do (
set "count=0"
for /r %%F in (%%P) do (
if exist "%%F" set /a count+=1
)
if !count! gtr 0 (
echo Deleting %%P files (!count! found^)...
del /s /q "%%P" >nul 2>&1
set /a deleted+=count
)
)
echo Deleted !deleted! build files.
:: Remove build directories
for %%D in (build Debug Release x64 x86) do (
if exist "%%D\" (
rmdir /s /q "%%D"
echo [OK] %%D
)
)
echo.
echo [DONE]
pause
Method 4: Clean with Summary Report
Show what was cleaned and how much space was recovered:
@echo off
setlocal enabledelayedexpansion
echo =============================================
echo BUILD CLEANUP WITH REPORT
echo =============================================
echo.
set "dirs_removed=0"
set "files_removed=0"
set "total_bytes=0"
set "dirs_to_clean=bin obj dist build publish artifacts .next .cache"
for %%D in (%dirs_to_clean%) do (
if exist "%%D\" (
echo Cleaning %%D...
:: Calculate directory size before removal (Summing bytes)
for /f "tokens=3" %%A in ('dir /s /a "%%D" 2^>nul ^| find "bytes" ^| find /v "free"') do (
set "csize=%%A"
set "csize=!csize:,=!"
set "csize=!csize:.=!"
set /a total_bytes+=!csize! 2>nul
)
rmdir /s /q "%%D" 2>nul
if not exist "%%D\" (
set /a dirs_removed+=1
) else (
echo [WARNING] Could not fully remove %%D
)
)
)
:: Clean temp/cache files (Recursive)
for /r %%F in (*.log *.tmp *.cache) do (
if exist "%%F" (
:: Add file size to total
for %%I in ("%%F") do set /a total_bytes+=%%~zI 2>nul
del /f /q "%%F" 2>nul
if not exist "%%F" (
set /a files_removed+=1
)
)
)
:: Convert bytes to MB (approximate to avoid large number overflow)
set /a recovered_mb=total_bytes / 1048576
echo.
echo =============================================
echo CLEANUP SUMMARY
echo Directories removed: !dirs_removed!
echo Files removed: !files_removed!
echo Space recovered: !recovered_mb! MB (approx)
echo =============================================
pause
Method 5: Pre-Build Clean Script
Integrate cleaning as the first step of a build pipeline:
@echo off
setlocal enabledelayedexpansion
echo =============================================
echo BUILD PIPELINE
echo =============================================
echo.
:: Stage 0: Clean (always runs first)
echo [0/4] Cleaning...
:: Remove known output directories
for %%D in (bin obj dist build publish) do (
for /f "delims=" %%P in ('dir /b /s /ad "%%D" 2^>nul') do rmdir /s /q "%%P" 2>nul
)
:: Remove specific generated files
del /q "*.log" 2>nul
del /q "build_info.txt" 2>nul
echo Clean.
:: Stage 1: Restore
echo [1/4] Restoring dependencies...
dotnet restore -v quiet
if !errorlevel! neq 0 (
echo [FAIL] Restore failed.
pause
exit /b 1
)
echo Done.
:: Stage 2: Build
echo [2/4] Building...
dotnet build -c Release --no-restore -v quiet
if !errorlevel! neq 0 (
echo [FAIL] Build failed.
pause
exit /b 1
)
echo Done.
:: Stage 3: Test
echo [3/4] Testing...
dotnet test -c Release -v quiet
if !errorlevel! neq 0 (
echo [FAIL] Tests failed.
pause
exit /b 1
)
echo Done.
:: Stage 4: Publish
echo [4/4] Publishing...
dotnet publish -c Release -o publish -v quiet
if !errorlevel! neq 0 (
echo [FAIL] Publish failed.
pause
exit /b 1
)
echo Done.
echo.
echo [SUCCESS] Clean build complete.
pause
Common Mistakes
The Wrong Way: Deleting the Source Directory
:: WRONG - Deletes source code instead of build output
rmdir /s /q "src"
:: Entire source code is gone!
Output Concern:
Always double-check that you are deleting build output directories (bin, obj, dist, build), not source directories (src, lib, app). A mistyped path in a clean script can destroy source code.
The Wrong Way: Cleaning Without Confirmation in Shared Directories
:: DANGEROUS - /s /q deletes everything without asking
rmdir /s /q "C:\Projects"
:: Deletes all projects, not just build output
Use specific, targeted paths and avoid cleaning parent directories. When cleaning shared or root-level directories, add a confirmation prompt.
Best Practices
- Target specific directories: Clean only known output directories like
bin,obj,dist, andbuild. - Use framework clean commands first:
dotnet clean,mvn clean, orgradlew cleanbefore manual deletion. - Integrate into build pipeline: Make cleaning the first stage of every build.
- Verify paths before deleting: Validate that paths point to output directories, not source code.
- Consider partial clean: Sometimes cleaning only specific outputs (like
distbut notnode_modules) is faster.
Conclusion
Cleaning build output directories before a new build in Batch Script ensures that every build is produced entirely from current source code with no stale artifacts. Whether using framework-specific clean commands (dotnet clean, mvn clean), recursive directory removal for solution-wide cleanup, or targeted deletion of specific output patterns, the clean step is the foundation of reproducible builds. By integrating the clean step as the first stage of every build pipeline, teams guarantee that build output accurately reflects the current state of the source code.