在批处理文件中递归查找 FolderName\file.name 组合和 return 完整路径

Find a FolderName\file.name combination(s) recursively in a batch file and return the full path(s)

我希望以递归方式在目录中的特定文件夹名称中查找特定文件名,如果存在一个或多个匹配项,则 return 查找完整路径。我正在寻找一种模式搜索,它甚至可以使用 3 部分查找,即 (folderA\folderB\file.name)。但是现在 2 就可以了。到目前为止,我的努力使我做到了这一点。但它非常慢。 16+ 秒找到匹配项。

   ::recursively find foldername\file.name combination

   cd C:\searchFolder
   for /r %a in (FolderName) do @if exist "%~fa\file.name" echo %~fa

我只需要深入 2 到 4 个级别并拉起第一个 folder\file.ext 匹配并获取完整路径。有没有更快的方法可以使用 dir 命令或排除列表,甚至是真正的 *folder\file 模式搜索。

让我们首先通过示例文件夹结构和 C:\SearchFolder 的每个子文件夹中名称为 file.name 的文件来阐明任务:

C:\SearchFolder
├───FolderA
│   │   file.name
│   │   
│   ├───FolderA
│   │   │   file.name
│   │   │   
│   │   ├───FolderA
│   │   │   │   file.name
│   │   │   │   
│   │   │   ├───FolderA
│   │   │   │       file.name
│   │   │   │       
│   │   │   └───FolderB
│   │   │           file.name
│   │   │           
│   │   └───FolderB
│   │       │   file.name
│   │       │   
│   │       ├───FolderA
│   │       │       file.name
│   │       │       
│   │       └───FolderB
│   │               file.name
│   │               
│   └───FolderB
│       │   file.name
│       │   
│       ├───FolderA
│       │   │   file.name
│       │   │   
│       │   ├───FolderA
│       │   │       file.name
│       │   │       
│       │   └───FolderB
│       │           file.name
│       │           
│       └───FolderB
│           │   file.name
│           │   
│           ├───FolderA
│           │       file.name
│           │       
│           └───FolderB
│                   file.name
│                   
└───FolderB
    │   file.name
    │   
    ├───FolderA
    │   │   file.name
    │   │   
    │   ├───FolderA
    │   │   │   file.name
    │   │   │   
    │   │   ├───FolderA
    │   │   │       file.name
    │   │   │       
    │   │   └───FolderB
    │   │           file.name
    │   │           
    │   └───FolderB
    │       │   file.name
    │       │   
    │       ├───FolderA
    │       │       file.name
    │       │       
    │       └───FolderB
    │               file.name
    │               
    └───FolderB
        │   file.name
        │   
        ├───FolderA
        │   │   file.name
        │   │   
        │   ├───FolderA
        │   │       file.name
        │   │       
        │   └───FolderB
        │           file.name
        │           
        └───FolderB
            │   file.name
            │   
            ├───FolderA
            │       file.name
            │       
            └───FolderB
                    file.name

可以使用以下方法创建包含文件的文件夹结构:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "BaseFolder=C:\SearchFolder"
for %%G in (A B) do (
    for %%H in (A B) do (
        for %%I in (A B) do (
            for %%J in (A B) do (
                md "%BaseFolder%\Folder%%G\Folder%%H\Folder%%I\Folder%%J"
                echo "%BaseFolder%\Folder%%G\Folder%%H\Folder%%I\Folder%%J">"%BaseFolder%\Folder%%G\Folder%%H\Folder%%I\Folder%%J\file.name"
            )
            echo "%BaseFolder%\Folder%%G\Folder%%H\Folder%%I">"%BaseFolder%\Folder%%G\Folder%%H\Folder%%I\file.name"
        )
        echo "%BaseFolder%\Folder%%G\Folder%%H">"%BaseFolder%\Folder%%G\Folder%%H\file.name"
    )
    echo "%BaseFolder%\Folder%%G">"%BaseFolder%\Folder%%G\file.name"
)
endlocal

示例结构在 运行 tree /F C:\SearchFolder 的 Windows 命令提示符 window 中输出 window。

应该在 C:\SearchFolder 的前三个子文件夹级别中搜索名为 file.name 的文件,并且找到的具有该名称的文件的路径必须以 FolderA\FolderB\ 结尾。

这可以使用以下批处理文件来完成:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "BaseFolder=C:\SearchFolder"
set "FolderName1=FolderA"
set "FolderName2=FolderB"
set "FileName=file.name"
for /F "delims=" %%I in ('dir "%BaseFolder%" /AD /B 2^>nul') do (
    for /F "delims=" %%J in ('dir "%BaseFolder%\%%I\%FolderName1%\%FolderName2%\%FileName%" /A-D /B 2^>nul') do echo "%BaseFolder%\%%G\%FolderName1%\%FolderName2%\%FileName%"
)
for /F "delims=" %%J in ('dir "%BaseFolder%\%FolderName1%\%FolderName2%\%FileName%" /A-D /B 2^>nul') do echo "%BaseFolder%\%FolderName1%\%FolderName2%\%FileName%"
endlocal

输出为:

"C:\SearchFolder\FolderA\FolderA\FolderB\file.name"
"C:\SearchFolder\FolderB\FolderA\FolderB\file.name"
"C:\SearchFolder\FolderA\FolderB\file.name"

所以只需要三个 FOR 命令就可以在 C:\SearchFolder 的 thirst 三个子文件夹中搜索文件 file.name 并存储在一个名为FolderB 位于名称为 FolderA.

的文件夹中

要了解使用的命令及其工作原理,请打开 command prompt window,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。

  • dir /?
  • echo /?
  • endlocal /?
  • for /?
  • md /?
  • set /?
  • setlocal /?
  • tree /?

阅读有关 Using command redirection operators 的 Microsoft 文档,了解 >2>nul 的解释。重定向运算符 > 必须在 上使用脱字符 ^ 进行转义,以便 命令行在 Windows 命令解释器处理此命令时被解释为文字字符执行命令 FOR 之前的行,它在一个单独的命令进程中执行嵌入的 dir 命令行,在后台启动 %ComSpec% /c' 中的命令行作为附加参数附加。

PS: rd /Q /S C:\SearchFolder 删除整个示例文件夹结构。

如果您想要限制级别,如您的问题中所述,(但未阐明),也许使用 Robocopy.exe 可以让您深入了解也只有所需数量的级别。

举个简单的例子,使用下面的第一个脚本创建您的测试目录结构:

@Echo Off
SetLocal EnableExtensions
Set "BaseFolder=%UserProfile%\Desktop\SearchFolder"
For %%G In (A B) Do (
    For %%H In (A B) Do (
        For %%I In (A B) Do (
            For %%J In (A B) Do (
                For %%K In (A B) Do (
                    For %%L In (A B) Do (
                        MD "%BaseFolder%\Folder%%G\Folder%%H\Folder%%I\Folder%%J\Folder%%K\Folder%%L"
                        CD.>"%BaseFolder%\Folder%%G\Folder%%H\Folder%%I\Folder%%J\Folder%%K\Folder%%L\file.name"
                    )
                    CD.>"%BaseFolder%\Folder%%G\Folder%%H\Folder%%I\Folder%%J\Folder%%K\file.name"
                )
                CD.>"%BaseFolder%\Folder%%G\Folder%%H\Folder%%I\Folder%%J\file.name"
            )
            CD.>"%BaseFolder%\Folder%%G\Folder%%H\Folder%%I\file.name"
        )
        CD.>"%BaseFolder%\Folder%%G\Folder%%H\file.name"
    )
    CD.>"%BaseFolder%\Folder%%G\file.name"
)

然后使用以下脚本列出您找到的路径:

@Echo Off
SetLocal EnableExtensions
Set "BaseFolder=%UserProfile%\Desktop\SearchFolder"
Set "FolderName1=FolderA"
Set "FolderName2=FolderB"
Set "FileName=file.name"

For /F "Tokens=*" %%G In ('%SystemRoot%\System32\Robocopy.exe
 "%BaseFolder%" "Null" "%FileName%" /FP /L /LEV:5 /NC /NDL /NJH /NJS /NS /S ^|
 %SystemRoot%\System32\findstr.exe /RI "\%FolderName1%\%FolderName2%\%FileName%$"
') Do Echo %%G
Pause
GoTo :EOF