Windows批处理根据文件名中的时间戳保留最新的N个文件 [英] Windows batch to keep the newest N files based on the timestamp in filename

查看:557
本文介绍了Windows批处理根据文件名中的时间戳保留最新的N个文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一个批处理脚本,以仅根据文件名中的时间戳记来保留最新的N个文件,并且仅在大小大于150 KB时才保留(如果大小较小,则意味着备份的文件已损坏,可以删除) . 我发现了类似的脚本,但仅适用于Linux.

该脚本首先应删除所有大小小于150 KB的文件,并保留最新的N个文件,并将文件名中的时间戳记作为参考,而不是文件的修改日期.

此.txt文件每天都会修改几次(周末除外). 每天备份文件几次,并在文件名中添加日期和时间.

文件名示例:Test_2019-01-16_21-57-34.txt

路径为:Z:\
操作系统是Windows 8

解决方案

可以使用以下批处理文件完成此任务:

@echo off
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

使用命令 PUSHD 将目录Z:\设置为当前目录,并在失败时退出goto :EOF退出批处理文件.

下一个命令 FOR 在后台命令行的单独命令过程中使用cmd.exe /C(更准确地说是%ComSpec% /C)执行:

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

命令 DIR 输出

  • 由于选项/A-D-H而未隐藏的文件的名称(属性不是目录,也不是隐藏的)
  • 以纯格式显示,由于选项/B
  • 而没有任何其他数据
  • 由于大小/OS
  • ,按大小顺序排在最前面,最小文件排在最后,最大文件排在最后
  • 匹配当前目录中的通配符模式Test_*.txt.

通过将错误消息从句柄 STDERR 重定向到设备,可以抑制 DIR 输出的错误消息,该错误消息在当前目录中找不到与这些条件匹配的任何目录条目. NUL .

阅读有关使用命令重定向操作符以获取2>nul的解释.当Windows命令解释器在执行命令 FOR 之前处理此命令行时,重定向操作符>必须在 FOR 命令行上转义字符^进行转义,以将其解释为文字字符. >,它将在后台启动的单独命令过程中执行嵌入的dir命令行.

FOR 捕获为处理已启动命令过程的 STDOUT 而编写的所有内容,并在启动cmd.exe自身终止后逐行处理捕获的输出.

带有选项/F

FOR 会忽略在选项/B中使用 DIR 时不会出现的空行.

FOR 还将忽略以分号开头的行,因为;是默认的行尾字符.文件名可以以分号开头,因此最好使用eol=|将行尾字符重新定义为完全没有文件名的竖线.在这种情况下,不必使用eol=|,因为 DIR 的输出只是以Test_开头的文件名,因此默认的eol=;不需要用eol=|覆盖.

FOR 将使用正常空格和水平制表符作为分隔符将每行分成子字符串(令牌),并将仅第一个空格/制表符分隔的字符串分配给指定的循环变量I.通过使用delims=定义字符串分隔符的空列表,可以禁用此行拆分行为.在这种情况下,实际上delims=并不是必需的,因为备份文件的文件名不包含空格.

IF 命令比较当前文件的si z e的值153600,即150 GiB )的文件不正确地由该 IF 条件.如果备份文件可以大于2 GiB,则有必要解决这一带符号的32位算术限制.

否则,在当前文件大于150 KiB的情况下,跳到标签DeleteOldFiles下面的行时退出第一个循环,因为此文件以及此文件后 DIR 输出的所有其他文件都有一个文件大小大于150 KiB.

第二个 FOR 循环在后台的单独命令过程中再次运行命令 DIR .但是 DIR 选项/OS/O-N代替,以根据文件名以相反的顺序输出文件名.日期最新的文件名首先由 DIR 输出,名字中日期最早的文件名最后输出,因为文件名中使用了国际日期格式.

第二个 FOR 命令行另外包含选项skip=5,以跳过前五个文件名,即最新的五个备份文件.

如果 DIR 输出的文件名超过五个,则所有其他比第一个五个输出文件名早的文件将被命令 DEL 由第二个 FOR 无条件执行.

最后,使用 POPD 将初始当前目录再次设置为当前目录.

要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面.

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

另请参阅:

另一个提示:将Z:\替换为 UNC 路径如果驱动器号Z:已分配给网络资源.并确保该批处理文件由具有访问网络资源权限的帐户执行,并且在此批处理文件作为计划任务执行的情况下,该帐户有权删除网络资源上该文件夹中的文件.另请参见将批处理文件作为计划任务执行时必须考虑什么?

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

解决方案

This task could be done with following batch file:

@echo off
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

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 in 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 also ignore lines starting 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=| to vertical bar 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=|.

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.

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?

这篇关于Windows批处理根据文件名中的时间戳保留最新的N个文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆