-1

I want to search for files say F1, F2, F3, F4, etc fir existence exist recursively in a BAT script. Currently a bad approach for this is IF EXIST F1 IF EXIST F2 .... ( DO SOMETHING ) ELSE ( DO SOMETHING ) Can anybody suggest good approach for this?

Arnav
  • 3
  • 1

3 Answers3

1

You can try using a for loop like this:

for /l %%a in (1, 1, 10) do (
    if exist "F%%a" (
        :: Do Something
    ) else (
        :: Do Something
    )
)

This iterates from 1 to 10 and places the value in %%a. Then concatenates the value with the filename.

You can replace "F%%a" for you filename (example myfile%%a).

  • I don't think this is what the OP asked for. OP wants to execute one branch if any file is found that meets the filter criteria, and the other if no file is found - One or the other branch executes exactly once. Your code executes one of the branches for each file. – dbenham Jan 28 '21 at 10:44
1

Your question is a bit unclear. I interpret it to mean you have a set of possible file names, and you want to execute one branch of code if there exists at least one file in the set, and a different branch if no file within the set exists.

Your bad approach most certainly is very bad - it only executes the ELSE if the very last Fn does not exist.

The DIR command returns success if at least one file is found, and error if no file is found. You don't need any output, so both stdout and stderr should be redirected to nul. You can use the conditional && and || command concatenation to test the returned error code. That is probably the most concise as well as the fastest solution you will find.

For example, if you have a discrete list of files then simply list them

dir f1 f2 f3 fn >nul 2>nul && (echo found) || (echo not found)

If it is possible that the last command in your success branch can return an error, then you must explicitly tack on a harmless command at the end that is guaranteed to succeed, else the error branch may mistakenly fire. I like to use (call ) as a command that always returns success.

dir f1 f2 f3 fn >nul 2>nul && (commandThatMayFail & (call )) || (echo not found)

If your list of files can be accurately represented using wildcards, then feel free to do so. For example, if you are looking for any file that begins with F or G, then

dir f* g* >nul 2>nul && (echo found) || (echo not found)

If the wildcards are not expressive enough to accurately represent your list, then you may be able to use DIR /B piped to FINDSTR with its crude regular expression capability.

dir * 2>nul | findstr "someRegexThatMatchesYourSet" >nul && (echo found) || echo (not found)

But beware that FINDSTR has some bugs that may or may not make it unsuitable for your situation.

A better option may be a 3rd party regular expression utility like grep or JREPL.BAT that has a more robust regular expression implementation.

For example, a JREPL solution could look like

dir /b * 2>nul | jrepl "someRegexThatMatchesYourSet" "" /match >nul && (echo found) || echo (not found)
dbenham
  • 127,446
  • 28
  • 251
  • 390
0

What about a for loop (see for /? for more information):

setlocal enabledelayedexpansion

set "filelist=file1 file2 file3 file4"
for /r %%a in (*) do (
   for /f "tokens=* delims=" %%c in ('echo/%%a^|findstr "!filelist!"') do (
      echo Found %%c.
   )
)

:end
endlocal
exit /b 0

If you do not know a priori for which files to search for, you can pass then (relatively or absolutely from cmd and then reading them into variable filelist as:

:nextinp
for /f "tokens=* delims=" %%i in ("%1") do (
   if not "%1"=="" (
      if not defined filelist (
         set "filelist=%1" & shift & goto:nextinp
      ) else (
         set "filelist=!filelist! %1" & shift & goto:nextinp
      )
   )
)

and call you program as prog file1 file2 file3....

mEm
  • 353
  • 3
  • 12