将文件名与 .bat 进行比较并将缺少的条目写入 .txt

comparing filenames with .bat and writing missing entries into .txt

我想比较文件夹中的一些文件,然后将缺少的文件写入文本文件。

我有一个文件夹

c:\sessions\

里面有文件。这些文件看起来像:

Blabla-1111-FOO
Blabla-1111-BAR1
Bleble-2222-FOO
Bleble-2222-BAR1
Bleble-2222-BAR2
Bleble-2222-BAR3
Bleble-2222-BAR4
Blublu-5678-FOO
Blublu-5678-BAR1
Blublu-5678-BAR2
Blublu-5678-BAR3
Blublu-5678-BAR4
Blublu-5678-BAR5
Bleble-6666-FOO
Bloblo-7777-FOO
Bloblo-8888-FOO
Bloblo-9999-FOO

我需要一个 .bat 文件,它将所有以 -FOO 结尾且不存在匹配的 -BAR 的文件记录到 noBARs.txt 中。所以在这种情况下 noBARs.txt 应该是这样的:

Bleble-6666-FOO
Bloblo-7777-FOO
Bloblo-8888-FOO
Bloblo-9999-FOO

可以有多个属于一个 -FOO 文件的 -BAR 文件。 提前谢谢大家。

您可以尝试以下方法:

@echo off
    
setlocal enabledelayedexpansion
set "source=c:\sessions"
set "output=noBARs.txt"
set "find=*foo"
set "repl=bar*"

1>"%output%" (
  for %%e in ("%source%\%find%") do (
    set "file=%%e"
    if not exist "!file:~0,-3!%repl%" (
      echo %%~ne
    )
  )
)

这将遍历文件名中包含 *foo 的所有文件。然后它将文件名的最后 3 个字符替换为 bar* 并检查文件是否存在。如果相应的 bar 文件不存在,它将原始文件名写入输出文件 noBARs.txt.


我根据 dEEkAy 的最后评论添加了脚本的替代版本,他在评论中指出以 FOO 结尾且后跟数字常量的文件也应进行测试。我仍然很不确定 dEEkAy 的确切意图是什么,但我假设文件名 *FOO* 的处理方式应与 *FOO.

相同

以下输入:

Blabla-1111-FOO
Blabla-1111-BAR1
Bleble-2222-FOO
Bleble-2222-BAR1
Bleble-2222-BAR5
Blublu-3333-FOO6
Blublu-3333-BAR1
Blublu-5678-FOO
Blublu-5678-FOO1
Blublu-5678-BAR2
Blublu-5678-BAR4
Bleble-6666-FOO
Bloblo-7777-FOO5
Bloblo-7777-BAR8
Bloblo-9999-FOO
Blublu-9999-FOO9
Bloblo-!^^!-FOO

将产生以下输出:

Bleble-6666-FOO
Bloblo-!^^!-FOO
Bloblo-9999-FOO
Blublu-9999-FOO9

脚本的替代版本也比原始版本更强大。它现在应该能够正确处理包含感叹号和插入符号的文件名和路径。不幸的是,它确实需要付出代价。由于 for 循环的每次迭代都会执行 call 命令,因此脚本变得很慢。也许具有更多批处理文件脚本编写经验的人可以提出更好的解决方案。

@echo off

setlocal disabledelayedexpansion
set "source=c:\sessions"
set "output=noBARs.txt"
set "find=foo"
set "repl=bar"

1>"%output%" (
  for %%e in ("%source%\*%find%*") do (
    set "path=%%~dpe"
    set "file=%%~ne"

    setlocal enabledelayedexpansion
    call :ReplaceEndOfString file match "%find%" "%repl%"

    if not exist "!path!!match!*" (
      echo !file!
    )
    endlocal
  )
)
exit /b

:ReplaceEndOfString (__in *source, __out *dest, __in find, __in repl) {
  set "temp=!%1:*%~3=%~3!"
  set "%2=!%1:%temp%=%~4!"
  exit /b
}

请记住,"%source%\*%find%*" 将匹配文件名中包含 %find% 的任何文件,而 "%source%\*%find%?" 仅匹配以 %find% 结尾的文件名,包括一个可以是任何东西的可选字符。


我刚好需要一些类似的代码,所以决定再看看。代码的主要瓶颈似乎是 call 命令的调用。虽然我没有找到解决这个问题的方法(除了使用宏之外),但 call 命令的执行时间可以大大缩短(大致为 2 倍)。

通过标签调用函数似乎比调用 set 命令慢很多。我不完全确定,但我记得由于需要重新扫描整个脚本文件而导致调用标签变慢的事情。文件名中的插入符和感叹号似乎也保持完好,因为延迟扩展阶段似乎发生在调用 set 命令之前。

@echo off

setlocal DisableDelayedExpansion
set "source=c:\sessions"
set "output=nobars.txt"
set "find=foo"
set "repl=bar"

1>"%output%" (
  for %%e in ("%source%\*%find%*") do (
    set "path=%%~dpe"
    set "file=%%~ne"

    setlocal EnableDelayedExpansion
    set "end=!file:*%find%=%find%!"
    call set "match=%%file:!end!=%repl%%%"

    if not exist "!path!!match!*" (
      echo !file!
    )
    endlocal
  )
)
exit /b