简体   繁体   中英

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

I'm looking to find a specific file name within a specific folder name in a directory recursively and return the full path if there is a match or multiple matches. I'm looking for a pattern search that can possibly even use a 3 part lookup ie (folderA\folderB\file.name). But 2 will do for now. So far my efforts have brought me to this. But it is terribly slow. 16+ seconds to find the match.

   ::recursively find foldername\file.name combination

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

I only need to venture about 2 to 4 levels deep and pull up the first folder\file.ext match and grab the full path. Is there a faster way to do this, with maybe the dir command or an exclusion list or even a true *folder\file pattern search.

Let us first clarify the task with an example folder structure and a file with name file.name in each subfolder of 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

That folder structure with the files can be created using:

@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

The example structure is output on running tree /F C:\SearchFolder in a Windows command prompt window.

There should be searched for files with name file.name in just the first three subfolder levels of C:\SearchFolder and the found files with that name must have a path ending with FolderA\FolderB\ .

That can be done using the following batch file:

@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

The output is:

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

So there are just three FOR commands necessary to search for file file.name in the thirst three subfolders of C:\SearchFolder being stored in a folder with name FolderB with is inside a folder with name FolderA .

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

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

Read the Microsoft documentation about Using command redirection operators for an explanation of > and 2>nul . The redirection operator > must be escaped with caret character ^ on FOR command lines to be interpreted as literal character when Windows command interpreter processes this command lines before executing command FOR which executes the embedded dir command line with using a separate command process started in background with %ComSpec% /c and the command line within ' appended as additional arguments.

PS: rd /Q /S C:\SearchFolder deletes the entire example folder structure.

If you're wanting to limit the levels, as mentioned in your question, (but not clarified) , perhaps using Robocopy.exe will allow you to drill down only the required number of levels too.

As a quick example, use the first script below to create your test directory structure:

@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"
)

Then use the following script to list your found paths:

@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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM