1

I need a batch script to keep only the newest N files based on the timestamp from filename and only if the size is bigger than 150 KB (if the size is less, means the backed up file is damage and can be deleted). I found similar scripts but only for Linux.

The script should first delete all the files with size less than 150 KB and keep the newest N files using as reference the timestamp from filename not the modified date of the files.

This .txt file is modify a few times per day except the weekend. The file is backed up a few times per day and the date and time are added in filename.

Example of filename: Test_2019-01-16_21-57-34.txt

Path is: Z:\
OS is Windows 8

Deco
  • 79
  • 1
  • 8
  • 3
    Break your task up into logical steps, then attempt each step one by one based on web/site searches, and the output of each command used when entered in a command prompt followed by `/?` – Compo Feb 12 '19 at 20:07
  • 1
    @Compo:I found how to delete the files with size less than a custom size. But I don't know how to filter the files with timestamp in filename. – Deco Feb 12 '19 at 20:15
  • 3
    Your timestamp is sortable, so if the files all have the prefix `Test_` a `for /f "delims=" %%A in ('Dir /B /O-N Test_*.txt') do (..)` and checking/counting the files with IFs should do. –  Feb 12 '19 at 20:43

1 Answers1

3

This task could be done with the following batch file:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
pushd "Z:\" || goto :EOF
for /F "eol=| delims=" %%I in ('dir /A-D-H /B /OS "Test_*.txt" 2^>nul') do if %%~zI LEQ 153600 (del "%%I") else goto DeleteOldFiles
:DeleteOldFiles
for /F "skip=5 eol=| delims=" %%I in ('dir /A-D-H /B /O-N "Test_*.txt" 2^>nul') do del "%%I"
popd
endlocal

The directory Z:\ is set as current directory using command PUSHD with exiting batch file execution with goto :EOF on failure.

Next command FOR executes with cmd.exe /c (more precisely %ComSpec% /c) in a separate command process in background the command line:

dir /A-D-H /B /OS "Test_*.txt" 2>nul

The command DIR outputs

  • the names of non-hidden files because of option /A-D-H (attribute not directory and not hidden)
  • in bare format without any additional data because of option /B
  • ordered by size with smallest file first and largest file last because of option /OS
  • matching the wildcard pattern Test_*.txt in current directory.

An error message output by DIR on not finding any directory entry in current directory matching these criteria is suppressed by redirecting the error message from handle STDERR to device NUL.

Read the Microsoft article about Using Command Redirection Operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line with using a separate command process started in background.

FOR captures everything written to handle STDOUT of started command process and processes the captured output line by line after started cmd.exe terminated itself.

FOR with option /F ignores empty lines which do not occur here on using DIR with option /B.

FOR would split up each line into substrings (tokens) using normal space and horizontal tab as delimiters and would assign just first space/tab delimited string to specified loop variable I. This line splitting behavior is disabled by using delims= to define an empty list of string delimiters. delims= is not really necessary here in this case because of the file names of the backup files do not contain a space character.

FOR would also ignore lines on which the first substring after splitting up the line into substrings (not necessarily the substring assigned to the loop variable) starts with a semicolon because of ; is the default end of line character. A file name can start with a semicolon and so it is better to redefine end of line character with eol=| or eol=? to vertical bar or question mark which no file name can contain at all. In this case eol=| would not be necessary because output by DIR are only file names starting with Test_ and so the default eol=; does not need to be overwritten with eol=|.

The IF command compares size of current file with value 153600 which is 150 KiB and the file is deleted if its size is less or equal this value.

Note: Windows command processor uses signed 32-bit arithmetic. So a file with more than 2,147,483,647 bytes (2 GiB) is not correct processed by this IF condition. It would be necessary to work around this signed 32-bit arithmetic limitation if backup files can be ever larger than 2 GiB.

Otherwise the first loop is exited with a jump to line below label DeleteOldFiles on current file being larger than 150 KiB because this file and all other files output by DIR after this file have a file size greater than 150 KiB.

The second FOR loop runs again command DIR in a separate command process in background. But the DIR option /OS is replaced by /O-N to get the file names output in reverse order according to file name. The file name with newest date is output first by DIR and the file name with oldest date in name is output last because of using international date format in the file names.

The second FOR command line contains additionally the option skip=5 to skip first five file names, i.e. the newest five backup files.

If DIR outputs more than five file names, all other files being older than the first five output file names are deleted by command DEL executed unconditionally by second FOR.

Finally the initial current directory is set again as current directory using POPD.

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • del /?
  • dir /?
  • echo /?
  • for /?
  • goto /?
  • if /?
  • popd /?
  • pushd /?

See also:

One more hint: Replace Z:\ by the UNC path if drive letter Z: is assigned to a network resource. And make sure the batch file is executed by an account which has the permissions to access the network resource and delete files in that folder on network resource in case of this batch file is executed as scheduled task. See also What must be taken into account on executing a batch file as scheduled task?

Mofi
  • 46,139
  • 17
  • 80
  • 143