1

I am very new to batch files. I am trying to write a script to find this file:

A\Org\App\B\C\SQL Scripts\Miscellaneous\CRErrorFinder.exe

Where:

  • A is any drive
    Example value C:
  • B a folder name
    Example value TEST
  • C a folder name, which should start from a known number e.g. 85.
    Example value 850-0

What I tried:

I can loop over the drives to get my root search folder, (something like C:\Org\App\ or D:\Org\App\ ), and then use two more loops for B and C. But is there a shorter way to achieve what I am doing here?

Compo
  • 36,585
  • 5
  • 27
  • 39
VikkyB
  • 1,440
  • 4
  • 16
  • 26
  • 2
    Please post the current code you are trying to use. – Squashman May 24 '18 at 20:12
  • 1
    This maybe will help you: (1) finding the file https://stackoverflow.com/questions/13876771/find-file-and-return-full-path-using-a-batch-file and (2) also browsing with FOR loop in the alphabet (browsing drive letters) https://stackoverflow.com/questions/21410817/for-loop-in-cmd-how-to-loop-a-to-z-for-drive-letters – s3n0 May 24 '18 at 20:18
  • Something like `DIR /B /S | FINDSTR /I /R /C:"Org.App.B.C.SQL.*Miscellaneous.CRErrorFinder.exe$"` – Mark Setchell May 24 '18 at 20:55
  • Can folder `B` have an arbitrary name? – aschipfl May 24 '18 at 22:56

1 Answers1

1

I think the only safe way is to establish loops for all the parts: the drive letter, the folder B (anything, *) and the folder C (85*). The inner-most loop in the following code example iterates once only and returns the file without accessing the file system as there is no wildcard * or ? (that is the nature of for); that is why if exist is used -- twice in order to match files only but not directories (note the trailing \ for the second one, not to be not fulfilled for folders):

for %%A in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do (
    for /D %%B in ("%%A:\Org\App\*") do (
        for /D %%C in ("%%~B\85*") do (
            for %%D in ("%%~C\SQL Scripts\Miscellaneous\CRErrorFinder.exe") do (
                if exist "%%~D" if not exist "%%~D\" (
                    echo(%%~D
                )
            )
        )
    )
)

The found path(s) is/are simply echoed.


There might be another way using dir /S and findstr, but you still have to loop through the drive letters:

for %%A in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do (
    dir /B /S /A:-D "%%A:\CRErrorFinder.exe" | findstr /R /I /X /C:".:\\Org\\App\\[^\\][^\\]*\\85[^\\]*\\SQL Scripts\\Miscellaneous\\CRErrorFinder\.exe"
)

Note that . means any character, \\ is a literal \, [^\\] is a character except \, * means the previous expression zero or more times and \. is a literal ..


Instead of looping through the alphabet you could gather the actually available drives on your system by wmic and capture them by for /F like this:

  1. All drives including network drives and such established by subst:

    for /F "skip=1" %%A in ('wmic LogicalDisk get DeviceID') do for /F "delims=:" %%A in ("%%A") do (
        rem %%A holds the pure drive letter.
    )
    
  2. Local drives only:

    for /F "skip=1" %%A in ('wmic Volume where "DriveLetter is not Null" get DriveLetter') do for /F "delims=:" %%A in ("%%A") do (
        rem %%A holds the pure drive letter.
    )
    

    Or (a bit faster):

    for /F "delims=:\ " %%A in ('mountvol ^| find ":\"') do (
        rem %%A holds the pure drive letter.
    )
    

These methods can be used for both of the aforementioned approaches instead of the for %%A loop.

aschipfl
  • 33,626
  • 12
  • 54
  • 99
  • For the drive letters, as an addition, _if you like_, `For /F "Tokens=* Delims=\ " %%A In ('MountVol^|Find ":\"') Do Echo %%A` or more simply, `For /F %%A In ('MountVol^|Find ":\"') Do Echo %%A`. _(I would guess it's quicker that loading `WMIC` too!)_ – Compo May 25 '18 at 01:06
  • @Compo, on my system (Windows 7) `mountvol` without arguments just throws out the help page... – aschipfl May 25 '18 at 09:23
  • aschipfl, did you try the command, `MountVol|Find ":\"`? or just `MountVol`? and did you not notice any mounted drive letters in the output. _I've been using that particular `For` loop certainly since `XP`, possibly `2000` and I've never known it not to work as intended!_ – Compo May 25 '18 at 09:30
  • @Compo, yes I did, and the result is `C:\`, `E:\`, `D:\`, which I interpreted as sample output rather than actual ones; however, these are just the local drives, of course, any network drives or such established by `subst` are not returned by `mountvol`, so it finally depends on what the OP wants. Thanks anyway! – aschipfl May 25 '18 at 09:44
  • By the way, `wmic Volume where "DriveLetter is not Null" get DriveLetter` gives the same result as `mountvol`, hence local drives only... – aschipfl May 25 '18 at 11:23