From this question:
for /f "tokens=3" %%g in ('java -version 2^>^&1 ^| findstr /i "version"') do (
#echo Output: %%g
set JAVAVER=%%g
)
How can I put this into a subroutine and call it, passing a path to the java executable? Here's an example of my problem:
#echo off
setlocal enabledelayedexpansion
call :GET_JAVA_VER "java"
goto END
:GET_JAVA_VER
for /f "tokens=3" %%g in ('%1 -version 2^>^&1 ^| findstr /i "version"') do #echo %%g
%1 -version 2>&1 | findstr /i "version"
goto :EOF
:END
endlocal
This outputs:
The filename, directory name, or volume label syntax is incorrect.
java version "10.0.1" 2018-04-17
It seems to me that the for loop is evaluating the parameter (%1) differently.
What's the difference?
EDIT
Possible duplicate of Java Version in a batch file
According to this answer, if that is indeed the problem, I would have to somehow transform the passed in path by adding quotes around each directory containing spaces. That sounds like a pain and I'm hoping there's another explanation; I still don't get why in this case just passing in "java" doesn't work.
(Note: using usebackq and back-quotes makes no difference)
It seems that piping the output to findstr was stripping the quotes for some reason. I deduce this because when I removed the ^| findstr /i "version" portion, this:
#echo off
setlocal enabledelayedexpansion
call :GET_JAVA_VER "java"
goto END
:GET_JAVA_VER
for /f "tokens=3" %%g in ('%1 -version 2^>^&1') do #echo %%g
goto :EOF
:END
endlocal
Outputs this:
"10.0.1"
Runtime
64-Bit
This modified script works (with full paths as well):
#echo off
setlocal enabledelayedexpansion
call:GET_JAVA_VER "java"
goto END
:GET_JAVA_VER
for /f "tokens=3" %%g in ('%~1 -version 2^>^&1') do (
echo %%~g
rem Stop after first line
goto :EOF
)
goto :EOF
:END
endlocal
Related
I try to find a string "blabla" inside a file. If I find the string I replace it with "bloblo", if not do nothing. And I want to do this operation for all the files that I have in a folder.
When I apply the script on one file, it works well. When I use a for loop it doesn't work. it does not enter inside the for loop
Here is my script:
set "Var1=blabla"
set "Var2=bloblo"
FOR %%i IN (C:\Users\UserName\Desktop\TEST\*.txt) DO (
find /c "%Var1%" %%i
if %errorlevel% equ 1 goto notfound
call PathFile\FUNCTION_REPLACE.cmd %Var1% %Var2% %%i
:notfound
)
I use a script "Function_replace" to replace the values, here is the script:
SetLocal EnableExtensions DisableDelayedExpansion
Set "search=%~1"
Set "replace=%2"
Set "File=%3"
For /F "Tokens=1*Delims=]" %%A In ('Find /V /N ""^<"%File%"^&Break^>"%File%"'
)Do (Set "line=%%B"
SetLocal EnableDelayedExpansion
(If Not "%%B"=="" (Echo(!line:%search%=%replace%!)Else Echo()>>"%File%"
EndLocal)
I used to use directly the call of my replace function for each files of my folder. But it takes a long time to go inside each file. That's why I want to check before going inside each file, if the string exists or not (by using find /c).
Can you spot where is the issue coming from?
Based upon your latest edit, here's an example which sends only the files containing the string to be replaced, to the sub-function:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "search=%~1"
Set "replace=%~2"
For /F Delims^=^ EOL^= %%A In ('FindStr /LIMP "%search%" *.*')Do Call :Sub "%%A"
GoTo :EOF
:Sub
Set "File=%~1"
For /F "Tokens=1*Delims=]" %%A In ('Find /V /N ""^<"%File%"^&Break^>"%File%"'
)Do (Set "line=%%B"
SetLocal EnableDelayedExpansion
(If Not "%%B"=="" (Echo(!line:%search%=%replace%!)Else Echo()>>"%File%"
EndLocal)
Please note that the FindStr command uses only example options, whilst the /M option is important to this solution you should check the output from FindStr /? to determine which of the others you would consider the most appropriate.
Why not simply list all files that has the string and exclude the files that don't? That seems like a more obvious plan to me:
#echo off
set "search=blabla"
for /f "delims=" %%i in ('findstr /m %search% "%USERPROFILE%\Desktop\TEST\*.txt"') do (
echo found "%search%" in "%%~fi"
)
If you want to still show files that does not contain the path, then #stephan already posted a comment on how to, no need for me to repeat.
I want to write a script to prompt user for file path and list all files found. The file path can contain wildcards. Something similar to this. But the batch script version of it. For example:
C:\Somewhere\user*\app\version-*.*\start.exe
The files might be located like this:
C:\Somewhere\user345\app\version-1.0\start.exe
C:\Somewhere\user898\app\version-1.2\start.exe
C:\Somewhere\user898\app\version-1.3\start.exe
I tried to use FOR and it turns out to be so much harder than expected because FOR does not support wildcards in the middle of a path.
Is there a way to list these files? (Maybe without using for?)
I think this recursive solution works pretty well; you may name it WCDIR.bat:
#echo off
setlocal
if "%~1" neq "" set "next=%~1" & goto next
echo Show files selected by several wild-cards
echo/
echo WCDIR wildcardPath
echo/
echo Each folder in the path may contain wild-cards
echo the last part must be a file wild-card
goto :EOF
:next
for /F "tokens=1* delims=\" %%a in ("%next%") do set "this=%%a" & set "next=%%b"
if defined next (
for /D %%a in ("%this::=:\%") do (
setlocal
cd /D "%%~a" 2>NUL
if not errorlevel 1 call :next
endlocal
)
) else (
for /F "delims=" %%a in ('dir /B /A:-D "%this%" 2^>NUL') do echo %%~Fa
)
exit /B
EDIT: I fixed a small bug in the last for /F command.
For example, the output of WCDIR.bat C:\Windows\Sys*\find*.exe command in my Windows 8.1 64-bits computer is:
C:\Windows\System32\find.exe
C:\Windows\System32\findstr.exe
C:\Windows\SysWOW64\find.exe
C:\Windows\SysWOW64\findstr.exe
You can try with the command Where /?
The WHERE command is roughly equivalent to the UNIX 'which' command. By default, the search is done in the current directory and in the PATH.
#echo off
Where /R "%programfiles%" *winrar.exe
pause
#echo off
:: Example d'input
set UserInput=*drive*
:: building the Pattern
set cmd=%Userinput%.exe
:: storage Where.exe command in a macro, the execution will be faster
set whereCmd=where.exe /r c:\windows\ %cmd%
:: execution of macro and output formatting
for /f %%a in ('%whereCmd%') do echo %%~nxa --^> %%a
pause
I am having a problem with Windows path expansion using a batch file where the variable contains a string from the Windows registry. See script below. I have tried multiple methods but I must be missing something simple.
#echo off
setlocal enabledelayedexpansion
for /f "tokens=2*" %%a in ('reg.exe query "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services" /t REG_EXPAND_SZ /f ServiceDll /s ^| grep.exe -ia "REG_EXPAND_SZ" ') do (
set registry_value2=%%b
call :regmerge
)
goto :endofscript
:regmerge
echo !registry_value2!
goto :eof
:endofscript
endlocal
Replace
set registry_value2=%%b
with
call set "registry_value2=%%b"
and remove the call to regmerge. The call will force the parser to do a second pass and replace the environment variables references.
Here is a possible solution with the use of findstr and storing the intermediate result in a temp file.
#echo off
rem tempfile
set tf=regfind.tmp
rem reg query output pipe into findstr and redirect to temnpfile
reg.exe query "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services" /t REG_EXPAND_SZ /v ServiceDll /s | findstr /C:SystemRoot > %tf%
rem iterate over each line in temp file and call merge
for /F "tokens=3*" %%a in (%tf%) do call :merge %%a
rem delete tempfile
del /q %tf%
goto :eof
:merge
rem SystemRoot is exapanded now...
echo %1
goto :eof
I'm not so new to batch scripting and have done a small amount of scripts for various other things but this script has stumped me.
I've actually pulled this idea from somewhere else as I'm not that deep into the for commands just yet.
What I'm trying to do with this script is search every subkey within the HKU rootkey for a specific subkey path. If that subkey path exists it'll modify a key value within that subkey path. But it seems to keep failing with no error.
This is what I have right now:
for /f %%a in ('reg query hku') do call :loop1 %%a
goto :end
:loop1
for /f %1 in (reg query %1\software\microsoft\dynamics) do call :loop2 %%b
goto :end
:loop2
if Errorlevel 1 goto :error
reg add %1\6.0\configuration /v configurationfile /t reg_sz /d \ /f
goto :end
:error
echo Error has occurrd.
goto :end
:end
Pause
When I run this batch I get the following.
c:\Users\-username-\Desktop\test>for /F %a in ('reg query hku') do call :loop1 %a
c:\Users\-username-\Desktop\test>call :loop1 HKEY_USERS\.DEFAULT
c:\Users\-username-\Desktop\test>for /f HKEY_USERS\.DEFAULT in (reg query HKEY_USER
S\.DEFAULT\software\microsoft\dynamics) do call :loop2 %b
c:\Users\-username-\Desktop\test>
It seems like it just stops running? when I check the errorlevel after it runs it returns "0" so I'd think I'd at least see the error message come up?
Am I missing something small I'm just looking over?
Run this to start with - see if what it returns is helpful to you:
This may need a later version of Windows - I'm not sure of the reg query options for earlier windows.
#echo off
for /f "delims=" %%a in ('reg query hku /s /f data /k ^| find /i "\software\microsoft\dynamics" ') do echo "%%a"
You need GOTO :eof to return from the subroutines.
for /f %%a in ('reg query hku') do call :loop1 "%%a"
pause
goto :eof
:loop1
for /f "%~1" in (reg query "%~1\software\microsoft\dynamics") do call :loop2 "%%b"
goto :eof
:loop2
if Errorlevel 1 echo Error has occurred. & pause & exit /B 1
reg add "%~1\6.0\configuration /v configurationfile" /t reg_sz /d \ /f
goto :eof
I found the bug(s). It was two places. RGuggiesberg, you are right. I needed the EOF in there. As foxidrive points out, the first line of "loop1" had some syntax issues. I was confusing myself.
Replaced:
for /f %1 in ('reg query %1\software\microsoft\dynamics') do call :loop2 %%b
with:
for /f %%b in ('reg query %1\software\microsoft\dynamics') do call :loop2 %%b
Now it's working fine. Thanks for the pointers!
So, I have probably a simple question but I cannot seem to find an easy answer.
Issue: I have a file that contains a set of lines such as:
%windir%\file.exe
%windir%\file2.dll
and so forth...
What I am trying to do is echo the actual file path to a second file such that the resulting output would be something like:
C:\Windows\file.exe
C:\Windows\file2.dll
and so forth...
The actual source file could have other variables such as %programfiles% but all of them have a resulting actual path.
I am currently using a for /f loop but when I echo the variable, I just get the environment variable returned rather than the actual path to the file.
Is there a solution out there for batch scripting?
The actual script is below. Note I am all for making this more efficient as time to get the information is important.
#echo off
setlocal enabledelayedexpansion
reg.exe query "HKLM\System\CurrentControlSet\Services" >> registry_hklm_installed_services_tmp.txt 2>nul
reg.exe query "HKLM\System\ControlSet001\Services" >> registry_hklm_installed_services_tmp.txt 2>nul
reg.exe query "HKLM\System\ControlSet002\Services" >> %temp_outpath%\registry_hklm_installed_services_tmp.txt 2>nul
reg.exe query "HKLM\System\ControlSet002\Services" >> registry_hklm_installed_services_tmp.txt 2>nul
for /f "delims=?" %%a in (registry_hklm_installed_services_tmp.txt) do (
set regkey=%%a
call :getvalue
)
goto :parsereg
:getvalue
reg.exe query "!regkey!\Parameters" /v ServiceDll > nul 2>&1 && goto regkeyexist
goto :eof
:regkeyexist
for /f "tokens=2*" %%b in ('reg.exe query "!regkey!\Parameters" /v ServiceDll') do set ImagePath=%%c
call :regag
goto :eof
:regag
echo !ImagePath! >> registry_hklm_installed_services_tmp2.txt
goto :eof
:parsereg
for /f "delims=?" %%a in (registry_hklm_installed_services_tmp2.txt) do echo %%a >> registry_hklm_installed_services_tmp3.txt
You can use the for /f command to cycle through the lines in the file like you are doing, and pass the line from the file to a subroutine inside the batch file, which will resolve it while it is being passed. Give the following:
Test.txt
%windir%\test.txt
%programfiles%\Test2.txt
This batch file will resolve the environment variables:
#echo off
setlocal ENABLEDELAYEDEXPANSION
for /f "delims=" %%i in (Test.txt) do call :Expand "%%i"
endlocal
goto TheEnd
:Expand
set _var=%1
echo !_var:"=!
:TheEnd
This is how the output looks when you run it:
c:\>Test.bat
C:\Windows\test.txt
C:\Program Files (x86)\Test2.txt
You can redirect the result to a new text file like this:
Test.bat > NewFile.txt
Or you can modify the original Test.bat to output the modified filename under Expand instead of echoing it to the console. It is important to include the quotes around %%i ("%%i") or spaces in the resolved paths will break into multiple variables when calling Expand (e.g., %1, %2, %3, etc.). The !_var:"=! removes the quotes.
This will also expand the variables.
#echo off
for /f "delims=" %%a in (Test.txt) do call echo %%a
pause
Test.txt
%windir%\test.txt
%programfiles%\Test2.txt
#ECHO OFF
SETLOCAL
FOR /f "delims=" %%a IN (q22726616.txt) DO (
FOR /f "delims=" %%b IN ('echo %%a') DO (
ECHO %%b
)
)
GOTO :EOF
I used a file named q22726616.txt containing your data for my testing.
[fixed following response - %%b line]