19

Can anyone help me create a batch file? Basically, my goal is to create a batch file that will keep the LATEST 7 .txt files (in other words, the newest) in the folder and subsequently delete the rest. That's IF there are more than 7 files in the folder.

The problem I'm having right now is the fact that the batch file that I have created deletes most of the files because their date is from a month or two or so. I want to keep the latest 7 files at all times no matter how old they are.

So this is what I have -

@echo off

setlocal enableextensions

rem ********************************************************************************
rem *******************************  LOCAL VARIABLES  ******************************
rem ********************************************************************************

SET TargetDirectory="C:\TEMP\test"

SET No_of_fles_to_keep=7

SET count=0 

set cnt=0

rem ********************************************************************************

cd /d %TargetDirectory%

REM timeout /T 500

 for %%x in (*) do set /a count+=1

 for %%A in (*.bat) do set /a cnt+=1

cd /d %TargetDirectory%

REM timeout /T 500

IF %count% gtr %No_of_fles_to_keep% forfiles -p %TargetDirectory% -s -m "*.txt" -d -%No_of_fles_to_keep% -c "cmd /c del @path"

echo %count% 

echo File count = %cnt% 

Any help is appreciated.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Knowledge42
  • 193
  • 1
  • 1
  • 5

4 Answers4

33

You can use DIR with /O-D to list the text files in descending timestamp order. FOR /F allows you to iterate over each file. SET /A is used to keep track of how many files have been listed so far. Now comes the tricky part.

Within a code block you normally need to use delayed expansion to work with the value of a variable that was set earlier in the same block. But delayed expansion can cause problems in a FOR loop if the FOR variable value contains !, and ! is valid in file names. I get around the problem by using SET /A to intentionally divide by 0 when the 7th file name has been read. This raises an error that causes the conditional code to execute that undefines the KEEP variable. From that point on, all remaining files are deleted.

@echo off
setlocal
set /a cnt=0
set "keep=7"
for /f "eol=: delims=" %%F in ('dir /b /o-d /a-d *.txt') do (
  if defined keep (
    2>nul set /a "cnt+=1, 1/(keep-cnt)" || set "keep="
  ) else del "%%F"
)

Update

Oh my goodness, I just realized there is a trivial solution. Just use the FOR /F SKIP option to ignore the first 7 entries after sorting by last modified date, descending.

for /f "skip=7 eol=: delims=" %%F in ('dir /b /o-d /a-d *.txt') do @del "%%F"

You don't even need a batch file. Just change %% to % if run from the command prompt.

dbenham
  • 127,446
  • 28
  • 251
  • 390
  • Thank you so much!! I just tested this and it worked like majic. – Knowledge42 Nov 14 '12 at 18:38
  • 4
    @user1821881 - I just added an even simpler solution. If you find a post that fully answers your question to your satisfaction, then you should accept it by clicking on the check mark near the upper left corner. That action lets others know the question has been answered, it awards you 2 reputation points, and awards the answer poster 15 rep points. Only 1 answer can be accepted. Once you reach 15 rep points you will gain the privilege to up-vote any answer you find useful, even answers to other people's questions. An up-vote awards the answer poster 10 points. – dbenham Nov 14 '12 at 18:54
  • @dbenham You have been extremely helpful. Some of this stuff may seem simple to some of you but im such a rookie. :/ Up-vote and checkmark to you, sir! – Knowledge42 Nov 14 '12 at 20:51
  • @dbenham hello sir! i understand that this is a pretty old thread. However, I found that your answer also helps my case. I just want to ask if you can possibly explain the Updated code you answered? I just need to tweak it to fit my needs and it would help me a lot to understand it first. Like the asker, I am such a rookie at this! Thanks a lot! :) – Smiley Jan 17 '14 at 23:23
  • 1
    @SmileyFace - `DIR /B /O-D` lists the files in reverse chronological order (newest first). `FOR /F` processes the result. `SKIP=7` skips the first 7 lines (the newest files). `EOL=:` effectively disables the EOL feature that ignores lines beginning with a given character (`;` by default) because a file path cannot begin with `:`. `DELIMS=` preserves the entire line. The `DEL` command is run for each line (value in `%%F`) that passes the FOR /F criteria. – dbenham Nov 12 '14 at 15:06
  • How do you specify the path which directory you want this to happen in or is it just current? – user2924127 Dec 23 '16 at 17:49
  • 1
    @user2924127 - You could include the path in the DIR command - something like `'dir /b /o-d "c:\your path*.txt"`. Or you could PUSHD to your directory before hand. – dbenham Dec 23 '16 at 18:06
  • 1
    EDIT - Added the `/A-D` switch to make sure we only look at files. – dbenham Dec 23 '16 at 18:08
  • Specifying the path inside the command improves safety since if you would do `cd path` before the command instead and the path did not exist for some surprising reason anymore then the `for ... del ...` command would be applied to system folder or to some other unintended folder which happens to be the previous/default active path. – Roland Pihlakas Dec 28 '20 at 20:31
2

The Batch file below use a simpler approach. It use findstr /N "^" command to number each file, then it just compare each number to keep first seven files and delete the rest...

@echo off
for /f "tokens=1* delims=:" %%a in ('dir /b /o-d *.txt ^| findstr /N "^"') do (
   if %%a gtr 7 del "%%b"
)

Antonio

Aacini
  • 65,180
  • 12
  • 72
  • 108
  • +1, Your answer forced me to re-evaluate and realize there is an even simpler solution. Use the FOR /F SKIP option - see my revised answer :-) – dbenham Nov 14 '12 at 18:55
  • Where I send the folder/path in this command ? For example "c:\tmp\" ??? – MCunha98 Aug 28 '18 at 23:23
0

If you don't write DOS scripts frequently which I don't, here is a summation of what others noted. Other examples here will need the batch file in the same folder that you're deleting from. To delete from another path: (Notice you have to add the path twice to the search and to the delete)

SET targetDir="C:\Test\Files\"
for /f "skip=7 eol=: delims=" %%F in ('dir /b /o-d /a-d %targetDir%*.txt') do @del "%targetDir%""%%F"

Thanks @dbenham, @SmileyFace, @user2924127 and all others who helped bring the answers.

PPL
  • 49
  • 7
-2

This will keep 7 latest .txt files and remove all other .txt files

Execute below command in same directory from which you want to delete files

On command prompt

for /f "skip=7 eol=: delims=" %F in ('dir /b /o-d /a-d *.txt') do @del "%F"

Inside batch script

for /f "skip=7 eol=: delims=" %%F in ('dir /b /o-d /a-d *.txt') do @del "%%F"
Stephan
  • 53,940
  • 10
  • 58
  • 91
Sarang A
  • 29
  • 5