Date 传输最新日期的文件名并删除较早日期的副本

Date 传输最新日期的文件名并删除较早日期的副本,date,duplicates,batch-file,Date,Duplicates,Batch File,目前,我必须将一堆excel表格上传到网络共享文件夹中。这些文件中的每一个都在文件名的末尾附加了创建它们的名称。然后我必须删除较早的版本,只留下最新的过时版本 基本上看起来是这样的 之前: apples 2019.07.01.xlsx apples 2019.07.07.xlsx oranges 2019.07.01.xlsx bananas 2019.07.01.xlsx 之后: apples 2019.07.07.xlsx oranges 2019.07.01.xlsx bananas 2

目前,我必须将一堆excel表格上传到网络共享文件夹中。这些文件中的每一个都在文件名的末尾附加了创建它们的名称。然后我必须删除较早的版本,只留下最新的过时版本

基本上看起来是这样的

之前:

apples 2019.07.01.xlsx
apples 2019.07.07.xlsx
oranges 2019.07.01.xlsx
bananas 2019.07.01.xlsx
之后:

apples 2019.07.07.xlsx
oranges 2019.07.01.xlsx
bananas 2019.07.01.xlsx
我偶然发现了一个可能的解决方案,那就是创建一个递归地遍历文件夹并执行此操作。然而,我不确定从哪里开始

我阅读,这是非常接近我想做的,但我有困难调整它,以适应我的需要。任何协助都将不胜感激

Edit2:这个代码对我有用:

@(
  SetLocal EnableDelayedExpansion
  ECHO OFF
  SET "_PathToCheck=Y:\T\DT"
  SET "_FileGlob=PLOG - * - ????.??.?? - *.xlsx"
  SET "_CurrentFile="
)

FOR /F "Tokens=1-2* Delims=-" %%A IN ('DIR /A-D /O-N /B "%_PathToCheck%\%_FileGlob%"') DO (
  IF /I "!_CurrentFile!" EQU "%%A-%%B" (
    ECHO.Deleting: "%_PathToCheck%\%%A-%%B-%%C"
    DEL /F /Q "%_PathToCheck%\%%A-%%B-%%C"
  ) ELSE (
    ECHO.
    ECHO.New File Found: "%%A-%%B"
    ECHO.-----------
    ECHO.Retaining: "%_PathToCheck%\%%A-%%B-%%C"
    SET "_CurrentFile=%%A-%%B"
  )
)
这是给你的最新版本,格雷格。 虽然最初我和其他几个人编写的版本适用于使用不同逻辑修改的日期(为所有文件名创建变量,然后再次对其排序,或者进行一组比较)我意识到我们仍然可以在一个循环中完成目标,不需要那么多临时变量,也不需要在那个场景和这个场景中有更复杂的逻辑,所以我花了几分钟创建了这个版本

本质上,我们只需要定义一个变量,该变量具有已找到的文件名,因为我们知道它们按日期顺序排列正确,并且只需要担心删除重复的命名文件

为此,我们可以使用SEt或
如果定义了
,我更喜欢这里的
如果定义了
,因为我可以使用脚本中已经定义的常规
如果
(),那么
()ELSE()
逻辑。(注意这里斜体的项目不是可以在CMD脚本中使用的术语,但我编写它们是为了澄清
IF
构造的正常逻辑)

我们可以使用
设置“
[变量名]
,并使用
|
&&
测试成功或失败,但这将是更多的重写,不必要的



以前的版本符合标准,仅文件名的左侧是唯一的。 示例输出: 确认脚本工作并显示输出和结果的屏幕截图:

@(
  SetLocal EnableDelayedExpansion
  ECHO OFF
  SET "_PathToCheck=Y:\T\DT"
  SET "_FileGlob=* ????.??.??.xlsx"
  SET "_CurrentFile="
)

FOR /F "Tokens=*" %%A IN ('DIR /A-D /O-N /B "%_PathToCheck%\%_FileGlob%"') DO (
  SET "_TFile=%%~nA"
  SET "_TFile=!_TFile:~0,-10!"
  IF /I "!_CurrentFile!" EQU "!_TFile!" (
    ECHO.Deleting: "%_PathToCheck%\%%~A"
    DEL /F /Q "%_PathToCheck%\%%~A"
  ) ELSE (
    ECHO.
    ECHO.New File Found: !_TFile!
    ECHO.-----------
    ECHO.Retaining: "%_PathToCheck%\%%~A"
    SET "_CurrentFile=!_TFile!"
  )
)
Y:\>Y:\t\DT.cmd

New File Found: bananas 
-----------
Retaining: "Y:\T\DT\bananas 2019.07.01.xlsx"

New File Found: oranges 
-----------
Retaining: "Y:\T\DT\oranges 2019.09.01.xlsx"
Deleting: "Y:\T\DT\oranges 2019.07.11.xlsx"

New File Found: apples 
-----------
Retaining: "Y:\T\DT\apples 2019.07.07.xlsx"
Deleting: "Y:\T\DT\apples 2019.07.01.xlsx"
@(
  SetLocal EnableDelayedExpansion
  ECHO OFF
  SET "_PathToCheck=Y:\T\DT"
  SET "_FileGlob=* ????.??.??.xlsx"
  SET "_CurrentFile="
  SET "_MatchList= "
)

FOR /F "Tokens=*" %%A IN ('DIR /A-D /ON /B "%_PathToCheck%\%_FileGlob%"') DO (
  SET "_TFile=%%~nA"
  SET "_TFileMD=!_TFile:~-5!"
  SET "_TVar=__!_TFile:~0,-5!!_TFileMD:~-2!.!_TFileMD:~0,2!"
  REM ECHO.Storing File: "%%~A" As: "!_TVar!"
  SET "!_TVar!=%%~A"
  IF /I "!_CurrentFile!" NEQ "!_TFile:~0,-10!" (
    ECHO.New File Found, Adding to Sort List: "!_TFile:~0,-10!"
    SET "_CurrentFile=!_TFile:~0,-10!"
    SET "_MatchList=!_MatchList! "__!_TFile:~0,-10!""
  )
)

ECHO.
ECHO.Delete Old Files
ECHO.-----------------

REM Loop the Matched Files:
FOR %%a IN (%_MatchList%) DO (
ECHO.
ECHO.Delete Old %%a Files
ECHO.-----------------
  REM Loop the SET sorted for each File Found and Skip the First one (Newest), deleting the others.
  FOR /F "Skip=1 Tokens=1-2 Delims==" %%A IN ('SET "%%~a" ^| SORT /R') DO (
    ECHO.Deleting: "%_PathToCheck%\%%~B"
    DEL /F /Q "%_PathToCheck%\%%~B"
    REM Remove the deleted file variable so we can print a list of retained files at the end:
    SET "%%A="
  )
)

ECHO.
ECHO.Retained Files:
ECHO.-----------------
FOR %%a IN (%_MatchList%) DO ( SET "%%~a" )
Y:\>Y:\t\DT_DM.cmd
New File Found, Adding to Sort List: "apples "
New File Found, Adding to Sort List: "bananas "
New File Found, Adding to Sort List: "oranges "

Delete Old Files
-----------------

Delete Old "__apples " Files
-----------------
Deleting: "Y:\T\DT\apples 2019.07.07.xlsx"
Deleting: "Y:\T\DT\apples 2019.12.01.xlsx"

Delete Old "__bananas " Files
-----------------

Delete Old "__oranges " Files
-----------------

Retained Files:
-----------------
__apples 2019.12.01=apples 2019.01.12.xlsx
__bananas 2019.01.07=bananas 2019.07.01.xlsx
__oranges 2019.11.07=oranges 2019.07.11.xlsx
@(
  SetLocal EnableDelayedExpansion
  ECHO OFF
  SET "_PathToCheck=Y:\T\DT"
  SET "_FileGlob=*.xlsx"
  SET "_CurrentFile="
  SET "_MatchList= "
)

FOR %%A IN ("%_PathToCheck%\%_FileGlob%") DO (
  ECHO.%%A| FINDStr /I " [0-9][0-9][0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.xlsx$" >NUL && (
    SET "_TFile=%%~nA"
    SET "_TVar=__!_TFile:~0,-10!%%~tA"
    ECHO.Storing File: "%%~A" As: "!_TVar!"
    SET "!_TVar!=%%~A"
    IF /I "!_CurrentFile!" NEQ "!_TFile:~0,-10!" (
      ECHO.
      ECHO.New File Found, Adding to Sort List: "!_TFile:~0,-10!"
      ECHO.
      SET "_CurrentFile=!_TFile:~0,-10!"
      SET "_MatchList=!_MatchList! "__!_TFile:~0,-10!""
    )
  )
)

ECHO.
ECHO.Delete Old Files
ECHO.-----------------

REM Loop the Matched Files:
FOR %%a IN (%_MatchList%) DO (
ECHO.
ECHO.Delete Old %%a Files
ECHO.-----------------
  REM Loop the SET sorted for each File Found and Skip the First one (Newest), deleting the others.
  FOR /F "Skip=1 Tokens=1-2 Delims==" %%A IN ('SET "%%~a" ^| SORT /R') DO (
    ECHO.Deleting: "%_PathToCheck%\%%~B"
    DEL /F /Q "%_PathToCheck%\%%~B"
    REM Remove the deleted file variable so we can print a list of retained files at the end:
    SET "%%A="
  )
)

ECHO.
ECHO.Retained Files:
ECHO.-----------------
FOR %%a IN (%_MatchList%) DO ( SET "%%~a" )

本质上,这和我的原始版本做的是一样的,只是现在我们知道我们应该寻找连字符

即:

@(
  SetLocal EnableDelayedExpansion
  ECHO OFF
  SET "_PathToCheck=Y:\T\DT"
  SET "_FileGlob=* ????.??.??.xlsx"
  SET "_CurrentFile="
)

FOR /F "Tokens=*" %%A IN ('DIR /A-D /O-N /B "%_PathToCheck%\%_FileGlob%"') DO (
  SET "_TFile=%%~nA"
  SET "_TFile=!_TFile:~0,-10!"
  IF /I "!_CurrentFile!" EQU "!_TFile!" (
    ECHO.Deleting: "%_PathToCheck%\%%~A"
    DEL /F /Q "%_PathToCheck%\%%~A"
  ) ELSE (
    ECHO.
    ECHO.New File Found: !_TFile!
    ECHO.-----------
    ECHO.Retaining: "%_PathToCheck%\%%~A"
    SET "_CurrentFile=!_TFile!"
  )
)
Y:\>Y:\t\DT.cmd

New File Found: bananas 
-----------
Retaining: "Y:\T\DT\bananas 2019.07.01.xlsx"

New File Found: oranges 
-----------
Retaining: "Y:\T\DT\oranges 2019.09.01.xlsx"
Deleting: "Y:\T\DT\oranges 2019.07.11.xlsx"

New File Found: apples 
-----------
Retaining: "Y:\T\DT\apples 2019.07.07.xlsx"
Deleting: "Y:\T\DT\apples 2019.07.01.xlsx"
@(
  SetLocal EnableDelayedExpansion
  ECHO OFF
  SET "_PathToCheck=Y:\T\DT"
  SET "_FileGlob=* ????.??.??.xlsx"
  SET "_CurrentFile="
  SET "_MatchList= "
)

FOR /F "Tokens=*" %%A IN ('DIR /A-D /ON /B "%_PathToCheck%\%_FileGlob%"') DO (
  SET "_TFile=%%~nA"
  SET "_TFileMD=!_TFile:~-5!"
  SET "_TVar=__!_TFile:~0,-5!!_TFileMD:~-2!.!_TFileMD:~0,2!"
  REM ECHO.Storing File: "%%~A" As: "!_TVar!"
  SET "!_TVar!=%%~A"
  IF /I "!_CurrentFile!" NEQ "!_TFile:~0,-10!" (
    ECHO.New File Found, Adding to Sort List: "!_TFile:~0,-10!"
    SET "_CurrentFile=!_TFile:~0,-10!"
    SET "_MatchList=!_MatchList! "__!_TFile:~0,-10!""
  )
)

ECHO.
ECHO.Delete Old Files
ECHO.-----------------

REM Loop the Matched Files:
FOR %%a IN (%_MatchList%) DO (
ECHO.
ECHO.Delete Old %%a Files
ECHO.-----------------
  REM Loop the SET sorted for each File Found and Skip the First one (Newest), deleting the others.
  FOR /F "Skip=1 Tokens=1-2 Delims==" %%A IN ('SET "%%~a" ^| SORT /R') DO (
    ECHO.Deleting: "%_PathToCheck%\%%~B"
    DEL /F /Q "%_PathToCheck%\%%~B"
    REM Remove the deleted file variable so we can print a list of retained files at the end:
    SET "%%A="
  )
)

ECHO.
ECHO.Retained Files:
ECHO.-----------------
FOR %%a IN (%_MatchList%) DO ( SET "%%~a" )
Y:\>Y:\t\DT_DM.cmd
New File Found, Adding to Sort List: "apples "
New File Found, Adding to Sort List: "bananas "
New File Found, Adding to Sort List: "oranges "

Delete Old Files
-----------------

Delete Old "__apples " Files
-----------------
Deleting: "Y:\T\DT\apples 2019.07.07.xlsx"
Deleting: "Y:\T\DT\apples 2019.12.01.xlsx"

Delete Old "__bananas " Files
-----------------

Delete Old "__oranges " Files
-----------------

Retained Files:
-----------------
__apples 2019.12.01=apples 2019.01.12.xlsx
__bananas 2019.01.07=bananas 2019.07.01.xlsx
__oranges 2019.11.07=oranges 2019.07.11.xlsx
@(
  SetLocal EnableDelayedExpansion
  ECHO OFF
  SET "_PathToCheck=Y:\T\DT"
  SET "_FileGlob=*.xlsx"
  SET "_CurrentFile="
  SET "_MatchList= "
)

FOR %%A IN ("%_PathToCheck%\%_FileGlob%") DO (
  ECHO.%%A| FINDStr /I " [0-9][0-9][0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.xlsx$" >NUL && (
    SET "_TFile=%%~nA"
    SET "_TVar=__!_TFile:~0,-10!%%~tA"
    ECHO.Storing File: "%%~A" As: "!_TVar!"
    SET "!_TVar!=%%~A"
    IF /I "!_CurrentFile!" NEQ "!_TFile:~0,-10!" (
      ECHO.
      ECHO.New File Found, Adding to Sort List: "!_TFile:~0,-10!"
      ECHO.
      SET "_CurrentFile=!_TFile:~0,-10!"
      SET "_MatchList=!_MatchList! "__!_TFile:~0,-10!""
    )
  )
)

ECHO.
ECHO.Delete Old Files
ECHO.-----------------

REM Loop the Matched Files:
FOR %%a IN (%_MatchList%) DO (
ECHO.
ECHO.Delete Old %%a Files
ECHO.-----------------
  REM Loop the SET sorted for each File Found and Skip the First one (Newest), deleting the others.
  FOR /F "Skip=1 Tokens=1-2 Delims==" %%A IN ('SET "%%~a" ^| SORT /R') DO (
    ECHO.Deleting: "%_PathToCheck%\%%~B"
    DEL /F /Q "%_PathToCheck%\%%~B"
    REM Remove the deleted file variable so we can print a list of retained files at the end:
    SET "%%A="
  )
)

ECHO.
ECHO.Retained Files:
ECHO.-----------------
FOR %%a IN (%_MatchList%) DO ( SET "%%~a" )
我们使用DIR以相反的排序顺序对文件名进行排序,这意味着具有较新日期的文件将显示在具有较旧日期的文件之前

这简化了删除文件的逻辑,也是我最初解决方案的关键

由于使用该方法,我们只需要检查文件名的第一部分(日期之前的部分)是否与找到的上一个文件相同

我们通过创建一个变量来保存当前文件的名称
\u CurrentFile
,并将其设置为空,这样在初始检查时,它将不匹配任何文件名

如果
\u CurrentFile
与找到的文件目录的文件名的第一部分(同样是日期之前的部分)匹配,那么我们可以安全地将其删除

如果
\u CurrentFile
与DIR cmd报告的文件的感兴趣部分不匹配,则我们将
\u CurrentFile
变量更新为该新值,并继续下一个要测试的文件结果

由于您不熟悉cmd/batch脚本,我想花一分钟的时间详细介绍一下脚本的作用以及原因,以便您自己继续: 首先我应该注意到,我们有一些关于如何迭代文件的选项,最常见的是
for,
for/F
,和
for/F
是循环文件的常用方法,有时在
for/F
文件列表中使用
DIR
cmd或者使用
WMIC
文件列表(不过,谢天谢地,WMIC最终被弃用,取而代之的是Powershell)

正如我们所知,您只需根据文件名和文件名中存储的日期进行选择,然后使用
dir
cmd按名称排序将是快速进行匹配的实用方法

现在来看看脚本的每个部分都在做什么 括号在CMD和批处理脚本中创建代码块,将同时计算给定括号内的所有内容

通过将
@
放在括号前面,任何带有它的命令(不在后面的括号内,或
DO
之后)都不会回显到屏幕上。这是为了停止显示此分区窗体并使输出混乱

  SetLocal EnableDelayedExpansion
我们正在启用延迟扩展,以便通过引用
!\u var!
而不是
%\u var%
来轻松评估
for
循环中变量的内容,从技术上讲,如果您的任何文件名中包含
,我们应该禁用此功能并将其重新写入b如果不是,那就好了

  ECHO OFF
我正在阻止脚本回显它正在执行的每一行,以减少输出的混乱。设置此命令意味着我不再需要在该代码块内的其他命令或该代码块外的未来代码之前使用@

  SET "_PathToCheck=Y:\T\DT"
  SET "_FileGlob=PLOG - * - ????.??.?? - *.xlsx"
  SET "_CurrentFile="
)
设置变量并用右括号结束代码块似乎是不言自明的,除了一个
\u FileGlob

@echo off
setlocal EnableDelayedExpansion

rem Initialize the "previous name"
set "lastName="
rem Process files in natural order, that is, the same order showed in the question
rem and set %%a to name and %%b to rest: date plus extension
for /F "tokens=1*" %%a in ('dir /B /A:-D /O:N *.xlsx') do (
   rem If previous name is not the same as current one
   if "!lastName!" neq "%%a" (
      rem Just update previous name and date
      set "lastName=%%a"
      set "lastDate=%%b"
   ) else (
      rem Remove the previous file
      ECHO del "!lastName! !lastDate!"
      rem and update the previous date
      set "lastDate=%%b"
   )
)
这是一个标准文件Glob,用于匹配要进行比较的文件名

*
匹配任意字符任意次数,
匹配任意字符一次。 这确保了如果我们遇到不符合我们期望的格式的文件,我们可以跳过它们

如果需要更明确的匹配,我们可以使用glob的
*.xlsx
,并使用
FINDStr
检查正则表达式模式,以确保格式完全符合需要

在下一部分中

 FOR /F "Tokens=1-2* Delims=-" %%A IN ('
  DIR /A-D /O-N /B "%_PathToCheck%\%_FileGlob%"
') DO (
   [Code]
)
没有
@echo off
setlocal EnableDelayedExpansion

rem Initialize the "previous name"
set "lastName="
rem Process files in natural order, that is, the same order showed in the question
rem and set %%a to name and %%b to rest: date plus extension
for /F "tokens=1*" %%a in ('dir /B /A:-D /O:N *.xlsx') do (
   rem If previous name is not the same as current one
   if "!lastName!" neq "%%a" (
      rem Just update previous name and date
      set "lastName=%%a"
      set "lastDate=%%b"
   ) else (
      rem Remove the previous file
      ECHO del "!lastName! !lastDate!"
      rem and update the previous date
      set "lastDate=%%b"
   )
)
@echo off
setlocal EnableDelayedExpansion

set "lastName="
for /F "delims=" %%a in ('dir /B /A:-D /O:N *.xlsx') do (
   set "currName="
   set "currFile="
   for %%b in (%%~Na) do (
      set "part=%%b"
      set "currFile=!currFile! !part!"
      if "!part:.=!" equ "!part!" set "currName=!currName! !part!"
   )
   if "!lastName!" neq "!currName!" (
      set "lastName=!currName!"
      set "lastFile=!currFile!"
   ) else (
      ECHO del "!lastFile:~1!.xlsx"
      set "lastFile=!currFile!"
   )
)
apples 2019.07.01.xlsx
apples 2019.07.07.xlsx
oranges 2019.07.01.xlsx
bananas 2019.07.01.xlsx
apples 2019.07.01 proof1.xlsx
apples 2019.07.07 proof1.xlsx
PLOG - Organic Valley - 2019.07.01 - (DAI) OG Cream Cheese.xlsx
PLOG - Organic Valley - 2019.07.07 - (DAI) OG Cream Cheese.xlsx
PLOG - Organic Valley - 2019.07.10 - (DAI) OG Cream Cheese.xlsx
del "apples 2019.07.01.xlsx"
del "apples 2019.07.01 proof1.xlsx"
del "PLOG - Organic Valley - 2019.07.01 - (DAI) OG Cream Cheese.xlsx"
del "PLOG - Organic Valley - 2019.07.07 - (DAI) OG Cream Cheese.xlsx"