0

For a few days I've been trying to solve the following problem with a batch script without success:

I need the full path to the file located in the folders: /common/Valheim/valheim.exe

This path should be searched for in all drives and at the end the path should be saved in a variable without the file name.

This find all valheim.exe files, but if i add the folders, i got no result.

setlocal enabledelayedexpansion
@echo off
(
   for %%a in ( c d e f g h) do (
      if exist "%%a:\" dir "%%a:\valheim.exe" /b /s /a-d (
        @set _variable=%%a
        @echo !_variable!
        )
    )
)
endlocal

And how can i use the variable outside of the function for copy files for example.

1 Answers1

-1

The code in the question does not work for multiple reasons:

  1. if exist "%%a:\" just tests existence of the drive, or more precisely, the root directory of the drive of which drive letter is assigned currently to the loop variable a.
  2. If the drive exists, the command DIR is executed to search the entire drive for a file with name valheim.exe. But the result of command DIR is not evaluated at all. DIR just outputs either all found files with name valheim.exe with full path or the error message File Not Found on not being able to find a file with name valheim.exe on entire drive. There is neither the exit code of command DIR evaluated nor is the output of DIR evaluated by the used code.
  3. The inner command block starting with (, having the two command lines @set _variable=%%a and @echo !_variable! and ending with ) is executed for each drive letter assigned to the loop variable a independent on IF condition being true or false for the current drive letter and independent on DIR having found a file or not. The ( marking the beginning of the command block at end of the line with the IF condition does not result in running this command block only if the IF condition is true and DIR found a file with name valheim.exe. The syntax of the IF condition is completely wrong here to make the execution of the two commands in the command block dependent on the IF condition.
  4. The environment variable _variable is for that reason always defined with the value h after the FOR loop finished.
  5. The environment variable _variable with value h is discarded by the command endlocal which results in discarding the entire environment variables list created as copy of the current environment variables list on starting the batch file by the command setlocal with the only modification of the (re)definition of the environment variable _variable several times within the FOR loop with having finally the string value h. So the environment variable _variable is not defined anymore after command endlocal on being not defined on starting the batch file at all or is still defined with the value this environment variable had on starting the batch file.
  6. DIR does not support searching for file system entries with a specific path left to the file/folder name with a variable path part at the beginning. There is no Windows command supporting that. It is only possible to search for a file or folder with a specific name and look on its fully qualified name to validate if the file/folder is within a specific directory tree.

The task can be done with a batch file using following single command line:

@for /F "skip=1" %%I in ('%SystemRoot%\System32\wbem\wmic.exe LOGICALDISK GET DeviceID 2^>nul') do @for /F "delims=" %%J in ('dir %%I\valheim.exe /A-D /B /S 2^>nul ^| %SystemRoot%\System32\findstr.exe /E /I /L /C:"\\common\\Valheim\\valheim.exe"') do @set "FilePath=%%~dpJ" & exit /B

@ left to a command suppresses the output of the command line after parsing it by the Windows command processor before execution. The three @ can be removed if the batch file contains more than just this line and has as first line @echo off.

There is first executed in background one more Windows command processor with the command line:

C:\Windows\System32\cmd.exe /c C:\Windows\System32\wbem\wmic.exe LOGICALDISK GET DeviceID 2>nul

The Windows Management Instrumentation Command-line utility uses the Win32_LogicalDisk class to get information about logical drives and outputs in Unicode with the character encoding UTF-16 LE with BOM a list of drive letters with a colon and the header line DeviceID.

The output of wmic.exe to standard output stream of background command process is captured by the command processor which is processing the batch file. The captured lines are processed line by line by FOR after in background started cmd.exe closed itself after wmic.exe terminated itself.

The first line with just DeviceID is skipped because of the usage of option skip=1. The other lines contain only the drive letter and the colon of a drive. So the outer FOR assigns one drive letter + colon to the loop variable I and runs the inner FOR.

The inner FOR starts again one more cmd.exe in background with a command line like:

C:\Windows\System32\cmd.exe /c dir C:\valheim.exe /A-D /B /S 2>nul | C:\Windows\System32\findstr.exe /E /I /L /C:"\\common\\Valheim\\valheim.exe"

The internal command DIR of cmd.exe searches

  • just for files because of option /A-D (attribute not directory)
  • with name valheim.exe in C:\ and all its subdirectories because of option /S
  • and outputs all files with that name in bare format because of option /B which means with just the file name with full path because of option /S.

The error message output by DIR on not finding any file with name valheim.exe to the handle standard error is suppressed by redirecting it to device NUL.

The file name(s) output by DIR are redirected to standard input of FINDSTR being used as filter. It does a case-insensitive search (/I) for the literally interpreted (/L and /C:) search string specified after /C: in double quotes. The find is only positive if the searched string is found at end of a line (/E) in which case the entire line is output by FINDSTR to standard output of the background command process.

The directory separator is \ on Windows and not / as on Linux/Mac. That is described by the Microsoft documentation about Naming Files, Paths, and Namespaces. FINDSTR interprets a backslash as escape character even in literally interpreted strings and for that reason it is necessary to escape each backslash in search string with one more backslash.

Read the Microsoft documentation about Using command redirection operators for an explanation of 2>nul and |. The redirection operators > and | must be escaped with caret character ^ on FOR command line to be interpreted as literal characters when Windows command interpreter processes this command line before executing the first command FOR.

The output by DIR filtered with FINDSTR is captured by cmd.exe processing the batch file and is processed line by line by the inner FOR after started background command process closed itself.

There is assigned just the full path of found file name of which fully qualified file name ends case-insensitive with \common\Valheim\valheim.exe to the environment variable FilePath and next the two loops and the entire batch file execution is exiting by using exit /B. If the batch file should do more with usage of FilePath, then the command GOTO must be used with a label which has the next line in the batch file to just exit the two loops and continue batch file processing on the line below the label line.

The environment variable FilePath can be used further in the Windows command process used to process the batch file.

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

  • dir /?
  • echo /?
  • exit /?
  • findstr /?
  • for /?
  • goto /?
  • set /?
  • wmic /?
  • wmic logicaldisk /?
  • wmic logicaldisk get /?

Read also:

  • Single line with multiple commands using Windows batch file
  • How to pass environment variables as parameters by reference to another batch file?
    It explains very detailed what happens on each execution of the commands SETLOCAL and ENDLOCAL and why both are not used here in this batch file because of the environment variable FilePath should still be defined with the found path after finishing processing of the batch file.
  • What is the reason for "X is not recognized as an internal or external command, operable program or batch file"?
    It explains in full details on the example of most important environment variable PATH how environment variables are managed on Windows. The environment variable FilePath exists only for cmd.exe processing the batch file once defined by the batch file. It does not exist for other processes already running or started next by another process than cmd.exe processing the batch file.
  • Microsoft documentation about Application Registration
    Many installers of applications register the executable as recommended by Microsoft. For that reason it is not necessary to search on all drives in all directories for an executable which is registered by the installer. A simple registry query is in this case enough to find out if an executable is installed at all and where it is installed. If the application registration is not done by an installer as recommended by Microsoft which is typical for games, the installers usually save the installation path either somewhere in the Windows registry or in a file in one of the common folders accessible using the predefined Windows Environment Variables output with their values on running set in a command prompt window.
Mofi
  • 46,139
  • 17
  • 80
  • 143