在批处理文件中递归查找FolderName ile.name组合并返回完整路径

问题描述 投票:0回答:2

我希望递归地在目录中的特定文件夹名称中查找特定文件名,如果存在匹配或多个匹配,则返回完整路径。我正在寻找一种模式搜索,甚至可以使用三部分查找,即(folderA oldB ile.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 层深度,然后拉出第一个文件夹 ile.ext 匹配并获取完整路径。有没有更快的方法来做到这一点,可能是 dir 命令或排除列表,甚至是真正的 *文件夹文件模式搜索。

batch-file recursion search design-patterns directory
2个回答
1
投票

让我们首先通过示例文件夹结构和

file.name
的每个子文件夹中名为
C:\SearchFolder
的文件来阐明任务:

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

示例结构是在 Windows 命令提示符窗口中运行

tree /F C:\SearchFolder
时输出的。

应仅在

file.name
的前三个子文件夹级别中搜索名为
C:\SearchFolder
的文件,并且找到的具有该名称的文件必须具有以
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 命令即可在

file.name
的三个子文件夹中搜索文件
C:\SearchFolder
,这些子文件夹存储在名为
FolderB
的文件夹中,并且位于名为
FolderA
的文件夹中。

要了解所使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完整、仔细地阅读每个命令显示的帮助页面。

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

阅读有关 使用命令重定向运算符的 Microsoft 文档,了解

>
2>nul
的说明。重定向运算符
>
必须在
FOR
命令行上使用脱字符号 ^ 进行转义,以便在 Windows 命令解释器在执行命令 FOR(执行嵌入的
dir
命令行)之前处理此命令行时将其解释为文字字符使用在后台启动的单独命令进程,并使用
%ComSpec% /c
'
中的命令行作为附加参数附加。

PS:

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


1
投票

如果您想限制级别,正如您的问题中提到的,(但未澄清),也许使用

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
© www.soinside.com 2019 - 2024. All rights reserved.