I cannot figure out how to get 'FORFILES' to delete files with a '.bak' extension that are 3 years old AND have it only look within sub/directories that are a WIP folder.
#ECHO OFF
setlocal enableextensions disabledelayedexpansion
forfiles /P "Y:\Africa" /S /M *.bak /D -1095 /C "cmd /c Del #path"
ECHO AFRICA - COMPLETED
Echo.
forfiles /P "Y:\Asia" /S /M *.bak /D -1095 /C "cmd /c Del #path"
ECHO ASIA - COMPLETED
Echo.
forfiles /P "Y:\Australia" /S /M *.bak /D -1095 /C "cmd /c Del #path"
ECHO AUSTRAILIA - COMPLETED
Echo.
forfiles /P "Y:\Europe" /S /M *.bak /D -1095 /C "cmd /c Del #path"
ECHO EUROPE - COMPLETED
Echo.
forfiles /P "Y:\North America\Canada" /S /M *.bak /D -1095 /C "cmd /c Del #path"
ECHO CANADA - COMPLETED
Echo.
forfiles /P "Y:\North America\Mexico" /S /M *.bak /D -1095 /C "cmd /c Del #path"
ECHO MEXICO - COMPLETED
Echo.
forfiles /P "Y:\North America\United States" /S /M *.bak /D -1095 /C "cmd /c Del #path"
ECHO UNITED STATES - COMPLETED
Echo.
forfiles /P "Y:\South America" /S /M *.bak /D -1095 /C "cmd /c Del #path"
ECHO SOUTH AMERICA - COMPLETED
Echo.
Pause
Goto :Selection
Currently the code is going into EVERY folder. searching for EVERY '.bak' file older than 3 years in each sub/directory. But I only wish for it to ONLY look in folders and its sub/directories if the folder is called WIP just to shave off half an hour from the scripts run time.
There is nothing to be deleted that applies to these criteria outside of the WIP folders as OTHER codes in the utility I am writing already take care of ‘.bak’ files in folders such as MASTERS (which we do not care if they are 3 years old or not, ‘.bak’ does not belong in there anyway nor is needed). However, if there IS something outside of the WIP folder that would apply to the criteria already set in the code, if its LOCKED (which we do not do for WIP folder files), it locks up the script and hangs at "Access is denied"...)
I will give an example
Africa has:
Y:\Africa\Egypt\wip
Y:\Africa\Kenya\WIP
Y:\Africa\South Africa\WIP
Asia has its many folders with individual countries like Africa has EXCEPT china has 4 folders that have WIP folders inside.
Many of folders labeled regionally are set up like this.
Is it possible to go into each path and skip into a sub/directory until it hits a WIP folder? like a '%%A wildcard' or something like you can do with 'FOR'?
You just need a mechanism to check that the current working directory ends in wip. There are a few different ways to do this but I chose to use a FOR /D /R command and then check to see if the child directory is equal to wip.
#echo off
for /d /r %%G in (wip*) do IF /I "%%~nxG"=="wip" (
PUSHD "%%G"
forfiles /M *.bak /D -1095 /C "cmd /c Del #path"
popd
)
You can put this in the root of your Y: drive and it will only process the directories that end in wip
EDIT:
If you can't run the batch file from the root directory of where you data is there are three ways to make the script change to a different directory.
If you just want to change to a different drive letter, you specify the driver letter with the colon
Y:
You can also use the CD command. Short for change directory.
CD mydirectory
If you need to change the directory and the drive letter at the same time you need to use the /D option with the CD command.
CD /D Y:\mydirecotry
And last but not least because it is my favorite way to do this is to use the PUSHD command.
PUSHD Y:\somedirectory
But if you use the PUSHD command you then need to use a POPD command to return to the original directory. Just like I am using in the code.
I have written a simple batch job for copying the files from one folder to another that are older than x-number of days using forfiles. But I need to count the number of files that have been copied. I tried various ways to do this but was unsuccessful. Could any body help me trough this?
#Echo off
Echo Starting the script for copying files to other folder.
set dt=%date:~10,4%-%date:~4,2%-%date:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%
set filesMovedCount=0
forfiles /p C:\symphonybackup\symphonybackup\Symphony\SymphonyArcheive /s /m *.* /d -30 /c "cmd /c echo #path >> C:\symphonybackup\symphonybackup\Symphony\%dt%.log & cmd /c copy #path C:\symphonybackup\symphonybackup\Symphony\SymphonyTemp"
Echo filesmovedcount:%filesMovedCount%
Echo finised copying the files
You could just pipe all of your copied file names to a file and then count the rows in the file. Here I added the additional stuff, you can just add the commands where the output gets piped to logfile where indicated. When done, it will echo the count and you delete the file.
#echo off
forfiles /p "rest of copy commands" >>logfile.txt
setlocal EnableDelayedExpansion
set "string=findstr /R /N "^^" logfile.txt | find /C ":""
for /f %%a in ('!string!') do set count=%%a
echo %count% files copied
del /Q logfile.txt
Mayby late answer to this, but when I try this:
set "string=findstr /R /N "^^" logfile.txt | find /C ":""
for /f %%a in ('!string!') do set count=%%a
I get one extra result since I get one empty row. So I did need have to add -1 to the result.
Atleast on my system...
I'm using a batch file now to delete all files ending in .snp that are older than 180 days. The code below works to delete all files ending in .snp under the root folder
C:\Program Files\Snapshots
But I recently discovered that within the Snapshots folder there are folders organized by date
"1-10-2014, 12-20-2014, 10-15-2014 etc.."
and that the below line of code doesn't work to recursively search through each directory and is therefore not deleting.
What changes should I make to this code to have it recursively search through folders within a root folder and delete files that are greater than 180 days?
forfiles /M *.snp /P "C:\Program Files\Snapshots" /S /D -180 /C "cmd /c del /F /Q #path"
Without the /D (Date) it workes for sub-folders
forfiles /M *.txt /P "C:\hlpme" /S /C "cmd /c del /f /q #path
but you obviously want the date to be there
then in CMD
forfiles /D -180 /M *.txt /P "C:\hlpme" /S /C "cmd /c del /f /q #path
The /D before the Pathname selects all files that have been changed more than 180 days ago
The best option for highest reliability is to combine the strengths of the For command with the FORFILES commands to allow each one to do what they do best.
Set str_Ext=*.snp
Set int_Age=-180
For /R "%~dp0" %%D IN (.) DO (
For /F "usebackq tokens=*" %%F IN (`FORFILES /P "%%~D" /m %str_Ext% /D %int_Age% 2^>nul`) DO (
Call :s_Del_File "%%~D" "%%~F"
)
)
Goto :EOF
:s_Del_File
Set "str_DIR=%~1"
Set "str_FIL=%~2"
Set "str_DIR=%str_DIR:~0,-1%"
DEL /F/Q/A "%str_DIR%%str_FIL%"
Goto :EOF
Within the second FOR command, the backquote (~ key) contains the FORFILES command and uses the console output to call a batch subroutine to delete the specified file.
Spaces in folder and file names will not slow this beast down, and the double quotes ["] around the Set commands will allow the process to work with folders and files that have parentheses in them or other exotic, but allowable characters.
I have this script which is created to backup a cube within an application. It runs every saturday and it created a sub folder within the application folder. Due to space requirements I've had to delete the oldest folder every week. I need to create a script to do that.
Here's the backup code:
:: Create folder for App Db if it does not exist
IF NOT EXIST %BACKUPDIR%%1"\"%2 GOTO MAKEDIR
GOTO CONT
:MAKEDIR
mkdir %BACKUPDIR%%1"\"%2
GOTO :CONT
:CONT
cd %BACKUPDIR%%1"\"%2
:: Get todays date
for /f "tokens=2,3,4 delims=/ " %%i in ('date /t') do (
set my_day=%%j
set my_month=%%i
set my_year=%%k )
set datestamp=%my_month%%my_day%%my_year%
::echo %datestamp%
:: Create date folder for app db
IF NOT EXIST %BACKUPDIR%%1"\"%2"\"%datestamp% GOTO MAKEDIRTIMEDATE
:MAKEDIRTIMEDATE
G:
cd %BACKUPDIR%%1"\"%2"\
mkdir %BACKUPDIR%%1"\"%2"\%datestamp%
:: Copy otl, csc, rul, rep files from App to Backup fodler
XCOPY %APPFOLDER%"\app\"%1"\"%2"\*.csc" %BACKUPDIR%%1"\"%2"\"%datestamp% /Y
XCOPY %APPFOLDER%"\app\"%1"\"%2"\*.rul" %BACKUPDIR%%1"\"%2"\"%datestamp% /Y
XCOPY %APPFOLDER%"\app\"%1"\"%2"\*.otl" %BACKUPDIR%%1"\"%2"\"%datestamp% /Y
XCOPY %APPFOLDER%"\app\"%1"\"%2"\*.rep" %BACKUPDIR%%1"\"%2"\"%datestamp% /Y
XCOPY %APPFOLDER%"\app\"%1"\"%2"\*.ind" %BACKUPDIR%%1"\"%2"\"%datestamp% /Y
cd %SCRIPTDIR%
:: Move data file from script dir to backupdir if data file exist If not exit out of code
IF NOT EXIST %SCRIPTDIR%%1"_"%2"_AllData.txt" GOTO EXIT
:END
MOVE %SCRIPTDIR%%1"_"%2"_AllData*.txt" %BACKUPDIR%%1"\"%2"\"%datestamp%
GOTO EXIT
:EXIT
exit /b
As you can see ever week a new folder is created with the creation data as its title (i.e. 102913). That folder is a subfolder of an application. I need a script to deleted the oldest folder.
So far I've tried (using test folders):
FORFILES -p "C:\Oracle\test\New folder\new folder" -s -m *.rul /D -<7> /C "cmd IF #isdir == TRUE" /c del #path
and
forfiles -p "C:\Oracle\test\New folder\new folder" -s -m *.rul /D -<7> /C "cmd /c del #path"
Any suggestion would be useful.
set "backupDir=C:\Oracle\test\New folder\new folder"
for /F "tokens=*" %%f in ('dir /ad /tc /o-d /b "%backupDir%"') do set "oldest=%backupDir%\%%f"
echo "%oldest%"
Get directory list ordered by creation date descending, only incuding directories, in brief format. Last line in list will be stored in variable %oldest% with the working directory prefixed.
I need to delete all empty folders from my application folder using windows command prompt?
How can I create a bat file like that?
Please help me.
You can use the ROBOCOPY command. It is very simple and can also be used to delete empty folders inside large hierarchy.
ROBOCOPY folder1 folder1 /S /MOVE
Here both source and destination are folder1, as you only need to delete empty folders, instead of moving other(required) files to different folder. /S option is to skip copying(moving - in the above case) empty folders. It is also faster as the files are moved inside the same drive.
A simpler way is to do xcopy to make a copy of the entire directory structure using /s switch. help for /s says Copies directories and subdirectories except empty ones.
xcopy dirA dirB /S
where dirA is source with Empty folders. DirB will be the copy without empty folders
for /f "usebackq" %%d in (`"dir /ad/b/s | sort /R"`) do rd "%%d"
from: http://blogs.msdn.com/b/oldnewthing/archive/2008/04/17/8399914.aspx
Of course I'd test it first without deleting before I do that command. Also, here's a modded version from the comments that includes folders with spaces:
for /f "usebackq delims=" %%d in (`"dir /ad/b/s | sort /R"`) do rd "%%d"
P.S. there are more comments in the blog post that might help you out so be sure to read those too before you try this out
You don't need usebackq:
FOR /F delims^= %%A IN ('DIR/AD/B/S^|SORT/R') DO RD "%%A"
Adding to corroded answer from the same referenced page is a PowerShell version http://blogs.msdn.com/b/oldnewthing/archive/2008/04/17/8399914.aspx#8408736
Get-ChildItem -Recurse . | where { $_.PSISContainer -and #( $_ | Get-ChildItem ).Count -eq 0 } | Remove-Item
or, more tersely,
gci -R . | where { $_.PSISContainer -and #( $_ | gci ).Count -eq 0 } | ri
credit goes to the posting author
from the command line:
for /R /D %1 in (*) do rd "%1"
in a batch file
for /R /D %%1 in (*) do rd "%%1"
I don't know if it's documented as such, but it works in W2K, XP, and Win 7. And I don't know if it will always work, but it won't ever delete files by accident.
This is a hybird of the above. It removes ALL files older than X days and removes any empty folders for the given path. To use simply set the days, folderpath and drive
#echo off
SETLOCAL
set days=30
set folderpath=E:\TEST\
set drive=E:
::Delete files
forfiles -p %folderpath% -s -d -%days% -c "cmd /c del /q #path "
::Delete folders
cd %folderpath%
%drive%
for /f "usebackq delims=" %%d in (`"dir /ad/b/s | sort /R"`) do rd "%%d"`
It will be worked fine. This is best way to delete old files and remove empty directories recursively.
following .bat file is,
forfiles /p [PATH] /s /m [FILE-PATTERN] /d -[DAYS] /c "cmd /c del #path"
for /f "delims=" %%d in ('dir [PATH] /s /b /ad ^| sort /r') do rd "%%d"
The placeholders needs to be replaced as follows (without the quotation marks):
[DAYS] = Max. age of the files in days, e.g. “10”
[PATH] = Path to search for old files and empty folders, e.g. “C:\Backup\”
[FILE-PATTERN] = Pattern that matches files to delete, e.g. “*.bkp”
The script has been successfully tested under Windows 7 and Windows Server 2003.
Install any UNIX interpreter for windows (Cygwin or Git Bash) and run the cmd:
find /path/to/directory -empty -type d
To find them
find /path/to/directory -empty -type d -delete
To delete them
(not really using the windows cmd prompt but it's easy and took few seconds to run)
#echo off
set /p "ipa= ENTER FOLDER NAME TO DELETE> "
set ipad="%ipa%"
IF not EXIST %ipad% GOTO notfound
IF EXIST %ipad% GOTO found
:found
echo DONOT CLOSE THIS WINDOW
md ccooppyy
xcopy %ipad%\*.* ccooppyy /s > NUL
rd %ipad% /s /q
ren ccooppyy %ipad%
cls
echo SUCCESS, PRESS ANY KEY TO EXIT
pause > NUL
exit
:notfound
echo I COULDN'T FIND THE FOLDER %ipad%
pause
exit
If you want to use Varun's ROBOCOPY command line in the Explorer context menu (i.e. right-click) here is a Windows registry import. I tried adding this as a comment to his answer, but the inline markup wasn't feasible.
I've tested this on my own Windows 10 PC, but use at your own risk. It will open a new command prompt, run the command, and pause so you can see the output.
Copy into a new text file:
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Classes\directory\Background\shell\Delete Empty Folders\command]
#="C:\Windows\System32\Cmd.exe /C \"C:\Windows\System32\Robocopy.exe \"%V\" \"%V\" /s /move\" && PAUSE"
[HKEY_CURRENT_USER\Software\Classes\directory\shell\Delete Empty Folders\command]
#="C:\Windows\System32\Cmd.exe /C \"C:\Windows\System32\Robocopy.exe \"%V\" \"%V\" /s /move\" && PAUSE"
Rename the .txt extension to .reg
Double click to import.
for /r "D:\Music" /d %F in (.) do #dir /b "%F" | findstr "^" >nul || rmdir %~fF
D:\Fun is the folder that contains empty folders
double quotation in the case of space in folder name (no need in this example)
A more modern and easier solution is:
forfiles /p C:\Path\To\Folder /c "cmd /c if #isdir==TRUE rd #file"
This will attempt to execute rd on all the directories located in C:\Path\To\Folder. Directories that have content in them will not be deleted.
If you exclude /p C:\Path\To\Folder then it'll run in the current directory.
If you add /s (before the /c) then it'll also look in sub-directories.
The following .cmd is an experiment (that works) to:
Deletes empty directories and included "Old"(-1days) files under %temp% & C:\Windows\Temp folders,
makes an cmd output log to a .txt file, about fouded & deleted folders/files .
%temp% = C:\Users(user)\AppData\Local\Temp | %userprofile%\AppData\Local\Temp
code:
:: This is a .cmd file
:: Use to:
:: Writes a Log about Temporary files & folders.
:: Cleans 'Windows Temp' folders/files. (%userprofile%\AppData\Local\Temp -&- %windir%\Temp)
:: - a 'Cleaning_LOGs.txt' will be created or updated in Documents Library. (%userprofile%\Documents\Cleaning_LOGs.txt)
::
#echo off
title Log&CleanTemp
: Set the Path of 'Log file' (%LogPath% variable)
set "LogPath=%userprofile%\Documents\Cleaning_LOGs.txt"
:: Note: ">> path\file.txt 2>&1" redirects cmd output to <path\to>\<log_file.txt>, (will be created if does not exist)
:: (if exist, adds the new log at the end of the file, without deleting previous logs)
: Set 'C:\Windows\Temp' (%WinTemp% var.)
set "WinTemp=%windir%\Temp"
: Seperator [Header] with Date-Time between (any) previous Logs in <log_file.txt>
echo: >> %LogPath% 2>&1
echo ======================================== >> %LogPath% 2>&1
echo %date% - %time% >> %LogPath% 2>&1
echo: >> %LogPath% 2>&1
echo Log Path: %LogPath% (this text file) >> %LogPath% 2>&1
echo: >> %LogPath% 2>&1
: Report Output & Log
:: Writes a log about temporary files & folders.
:: Note: ( %temp% = C:\Users\<user>\AppData\Local\Temp = %userprofile%\AppData\Local\Temp )
:: ( 'WinTemp' = C:\Windows\Temp = %windir%\Temp )
echo: >> %LogPath% 2>&1
echo __________ Empty (0 size) , Old (-1days) files: >> %LogPath% 2>&1
ForFiles /p "%temp%" /s /d -1 /c "cmd /c if #fsize==0 ECHO #path " >> "%LogPath%" 2>&1
ForFiles /p "%WinTemp%" /s /d -1 /c "cmd /c if #fsize==0 ECHO #path " >> "%LogPath%" 2>&1
echo: >> %LogPath% 2>&1
echo __________ All Old (-1days) files: >> %LogPath% 2>&1
ForFiles /p "%temp%" /s /d -1 /c "cmd /c ECHO #path " >> "%LogPath%" 2>&1
ForFiles /p "%WinTemp%" /s /d -1 /c "cmd /c ECHO #path " >> "%LogPath%" 2>&1
:: Note: "ForFiles" /p=Path /s=SubDir /d=Days(dd) /c=cmd "forfiles /?" for info about command's Variables (#path, #file, etc.)
: Get permissions (unlock files/folders) (OPTIONAL)
:: Uncomment to make it work, IF needed.
::echo: >> %LogPath% 2>&1
::ForFiles /p "%temp%" /s /d -1 /c "cmd /c TAKEOWN /f * /r /d y && ICACLS #file /grant *S-1-3-4:F /t /c /l /q"
: Clean proper files & Log it
:: Test: ForFiles /p "%temp%\" /s /d -1 /c "cmd /c if #fsize==0 DEL /f /s /q #file" >> "%LogPath%" 2>&1
:: ERROR: Invalid argument/option - '#fsize==0'
echo: >> %LogPath% 2>&1
echo __________ Deleted files: >> %LogPath% 2>&1
forfiles /p %temp%\ /s /d -1 /c "cmd /c DEL /f /s /q #path" >> "%LogPath%" 2>&1
forfiles /p %WinTemp%\ /s /d -1 /c "cmd /c DEL /f /s /q #path" >> "%LogPath%" 2>&1
echo: >> %LogPath% 2>&1
echo __________ Deleted empty directories: >> %LogPath% 2>&1
for /f "delims=" %%d in ('dir %temp%\ /s /b /ad ^| sort /r') do RD "%%d" >> "%LogPath%" 2>&1
for /f "delims=" %%d in ('dir %WinTemp%\ /s /b /ad ^| sort /r') do RD "%%d" >> "%LogPath%" 2>&1
:: Note: 'RD' = Remove-Directory (delete)
: Open Log file
:: this opens the log file [(my) Documents\Cleaning_LOGs.txt]
explorer.exe %LogPath%
:: https://stackoverflow.com/questions/7831286/how-to-delete-empty-folders-using-windows-command-prompt/46617314#46617314
Note that:
The trigger to Experiment with this, as part of a 'pre-process', was to prevent the specific (obsolete) driver of the (also obsolete) sound card from automatically reinstalling at each boot. And clean (ghosted) hidden Devices and more other. (...) (this note was just about to get an idea for the use)
So, in a few words:
This is the part that cleans up the 'temp' garbage left behind and gives a report.
well, just a quick and dirty suggestion for simple 1-level directory structure without spaces, [edit] and for directories containing only ONE type of files that I found useful (at some point from http://www.pcreview.co.uk/forums/can-check-if-folder-empty-bat-file-t1468868.html):
for /f %a in ('dir /ad/b') do if not exist %a\*.xml echo %a Empty
/ad : shows only directory entries
/b : use bare format (just names)
[edit] using plain asterisk to check for ANY file (%a\* above) won't work, thanks for correction
therefore, deleting would be:
for /f %a in ('dir /ad/b') do if not exist %a\*.xml rmdir %a
This can be easily done by using rd command with two parameters:
rd <folder> /Q /S
/Q - Quiet mode, do not ask if ok to remove a directory tree with
/S
/S - Removes all directories and files in the specified directory
in addition to the directory itself. Used to remove a directory tree.