在批处理脚本中获取包含文件名中字符串的最新文件的绝对路径

Get absolute path of newest file containing string in filename in batch script

我有一个批处理文件,我想获取最新的 "manifest" 文件,所以我希望能够为此使用 for 循环,但我不确定是否正确语法。

这是我的:

for /R %imagePath% %%F in (*.manifest.*) do (set manFile=%%F)

哪个对 return "C:/some/path/to/file.manifest.ext" 正确,但不一定是最新的。我看到其他类似这个使用 dir 的问题,但后来我没有得到完整的路径。我用 dir 做的尝试看起来像:

for /R %imagePath% %%F in ('dir /od *.manifest.*.*') do (set manFile=%%F)

这没有给我预期的输出。

完成此任务的最佳方法是什么?

set "manFile="
for /f "tokens=2,*" %%a in ('
    robocopy "%imagePath%" "%temp%" *.manifest.* /is /l /nocopy /s /njh /njs /ndl /nc /ns /ts
    ^| sort /r
') do if not defined manFile set "manFile=%%b"

这使用 for /f 来处理 robocopy 命令的输出,该命令将生成具有 UTC 时间戳的匹配文件列表,该时间戳将被反向排序,因此最新的文件将是首先在列表中。

MC ND 的解决方案很聪明。但是当我尝试使用“.”作为文件掩码时,我得到了错误的结果。原因是 robocopy 列出了来自 源文件夹和(虚拟)目标文件夹的相应文件,在本例中为 %TEMP%。您可以通过将 /xx 开关添加到 robocopy 来解决这个问题,或者只使用一个空的目标文件夹。由于我不能 100% 确定 /xx 开关将始终有效,因此我为目标文件夹指定了一个随机名称(希望该名称不存在)。

原始代码的第二个缺点是 FOR 循环将不必要地执行到文件列表的末尾,该列表可以是任意长的。

以下代码修复了目标文件夹问题,在获得结果后缩短了循环,此外还导出了树中最年轻文件的文件名和时间戳:

@echo off
setlocal

set "srcpath=%~1"
if not DEFINED srcpath set srcpath=%CD%
set /A skip=%2 - 1
set opt=
if DEFINED skip if %skip%0 GTR 0 set "opt=skip=%skip%"

set MASK=*.manifest.*
for /f "%opt% tokens=1,2*" %%a in ('
    robocopy "%srcpath%" %RANDOM%_%RANDOM% %MASK% /l /s /ts /njh /njs /ndl /nc /ns ^| sort /r
') do set "tstamp=%%a %%b" & set "youngestfile=%%c" & goto :ex

:ex
echo %youngestfile%    %tstamp%

脚本现在最多可以接受 2 个参数。第一个参数是源文件夹,如果省略则默认为当前文件夹。第二个参数是数字,允许搜索第 n 个最小的文件。因此,例如 "lastfile . 2" 将 return 以当前文件夹为根的树中第二年轻的文件。这是 FOR 循环的副作用,从列表顶部开始使用最新的文件。