Reuse result of "where" command - windows

I need to find the specific location of java 64-bit on a windows machine. I thought about using where java to find all possible locations. In the next step I would need to isolate the proper location which starts with: C:\Program Files\Java\... and then execute the command as following:
cmd /K %var% -jar %~dp0XYZ.jar
Is this the proper way to find the java path which might change over time? If yes, how can I get the path from where into a variable?
For the output of where assume this:
C:\Program Files (x86)\Common Files\Oracle\Java\javapath\java.exe
C:\Program Files\Java\jdk1.8.0_144\bin\java.exe
C:\Program Files\Java\jdk1.8.0_144\jre\bin\java.exe
It wouldn't matter if it takes second or third result, as both are 64 bit in this case. But as I can't guarantee that output, the only way to identify the 64-bit version is with C:\Program Files\Java\

The following bat script (commented for explanation) should do the trick:
#ECHO OFF
rem SETLOCAL EnableExtensions DisableDelayedExpansion
set "_flagexe64=:\Program Files\Java\"
set "_javaexe64="
for /f "delims=" %%G in ('where java.exe') do (
rem next two lines for debugging only
echo checking "%%~G"
"%%~G" -version
if not defined _javaexe64 (
set "_javaexe64=%%~G"
call :check64
)
)
rem final check
if not defined _javaexe64 (
1>&2 echo sorry, no java.exe found under "%_flagexe64%"
goto :eof
)
rem java.exe found:
echo "%_javaexe64%"
goto :eof
:check64
call set "_aux=%%_javaexe64:%_flagexe64%=%%"
if "%_aux%" == "%_javaexe64%" set "_javaexe64="
goto :eof

Related

Get the last name of a directory path in batch

I've been tasked with writing installation scripts for my company that will be able to install printer drivers on a users computer.
What I have done so far is I've made the script accept a parameter (the printer type brother, xerox, etc..) from there it will gather the relative path to the drivers, and run a forfiles command on the path outputting all the drivers, after that it will ask the user for the correct driver copy it from the network drive to the users desktop, and run it.
What I need to do is the running part, I need to copy the driver to the desktop and somehow get the last directory part (example: user\desktop\test.exe I need to gather the last part test.exe) how can I go about doing this in a functional way?
Basically I would need to split the path by \ and grab the last entry of that list, is this possible in batch?
#echo off
type banner.txt
if [%1]==[] goto usage
:verify_argv
IF '%1'=='canon' GOTO get_canon_path
IF '%1'=='xerox' GOTO get_xerox_path
IF '%1'=='hp' GOTO get_hp_path
IF '%1'=='dell' GOTO get_dell_path
IF '%1'=='brother' GOTO get_brother_path
goto :eof
:get_canon_path
set dir_path=\\mgtutils01\windows7apps\PRINTERS\Canon
goto :install_drivers
:get_xerox_path
set dir_path=\\mgtutils01\windows7apps\PRINTERS\Xerox
goto :install_drivers
:get_hp_path
set dir_path=\\mgtutils01\windows7apps\PRINTERS\HP
goto :install_drivers
:get_dell_path
set dir_path=\\mgtutils01\windows7apps\PRINTERS\Dell
goto :install_drivers
:get_brother_path
set dir_path=\\mgtutils01\windows7apps\Brother\Drivers
goto :install_drivers
:usage
#echo Usage: .\driver [PRINTER_TYPE]
exit /B 1
:install_drivers
#echo Finding drivers...
pushd "%dir_path%"
forfiles /s /m *.exe /c "cmd /c echo #relpath"
set /p to_install="Copy the path of the correct driver and paste here: "
#echo Copying file to %USERPROFILE%, please wait..
xcopy %to_install% "%USERPROFILE%\Desktop"
#echo Installing driver..
pushd "%USERPROFILE%\Desktop"
To get the last element of a file or directory path, you can:
either use a for loop and its ~ modifiers:
set "ITEM=user\desktop\test.exe"
for %%I in ("%ITEM%") do set "NAME=%%~nxI"
echo %NAME%
or call a sub-routine by the call command, pass the path as an argument and again use ~ modifiers:
set "ITEM=user\desktop\test.exe"
call :SUB "%ITEM%"
goto :EOF
:SUB
set "NAME=%~nx1"
goto :EOF
For both variants, the ~nx part extracts the base name (n) and the extension (x) from the last element of the path stored in the reference (%%I or %1). Type for /? and call /? into a command prompt window and read the help texts; you will find all the possible ~ modifiers of for variable references and argument references, respectively.

autocomplete path in cmd batch

Windows CMD prompt's auto-complete, (similar feature in other terminals), comes very handy sometimes when you are not sure of the right path or file name.
Bottom line is, how to use this feature in batch scripting.
Example: the script "C:\Program Files\Java\jre1.8.0_92\bin\javaw.exe" -jar post.jar
the thing here is that java version is not always the same, so it needed to be something like this
"C:\Program Files\Java\jre*\bin\javaw.exe" -jar post.jar
you can't use wildcards in the middle of a path, but you can at the end (the last element). Because you need it in between, split it up:
for /f "delims=" %%a in ('dir /b /ad /on "C:\Program Files\Java\jre*"') do set ver=%%a
set "exec=C:\Program Files\Java\%ver%\javaw.exe"
"%exec%" -jar post.jar
This will get you the path with the highest version number, if there are more than one.
Wildcards are supported by only some commands. Moreover, cmd restricts wildcards in a file path only in a path leaf i.e. in token behind last backslash…
On an unknown Windows system: if you do not have control on environment variables then you need to find a file path e.g. as follows (note the _checkPath variable assignment is changed to get reasonable output as I do not have java installed):
#ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
rem assign path with a wildcard * not in path leaf
set "_checkPath=C:\Program Files\Java\jre*\bin\javaw.exe"
rem delete or comment-up next line i.e. my test data set "_checkPath=..."
set "_checkPath=%ProgramFiles%*\Microsoft SQL Server\1*\LocalDB\Binn\sqlservr%1.exe"
set "_itemFirst="
rem previous line: delete variable; next line: show setting
set _checkPath
echo(---
rem next two lines: ensure that a wildcard * not in path leaf is not allowed
echo dir /B /S "%_checkPath%"
dir /B /S "%_checkPath%"
echo(---
rem find all files by parsing powershell output ( note proper escaping ^^^| )
for /F "usebackq tokens= 1* delims=: " %%G in (`
powershell -C Get-ChildItem '"%_checkPath%"' -Recurse ^^^| Format-List -Property FullName
`) do (
rem assign first found item
if not defined _itemFirst set "_itemFirst=%%~H"
rem assign every found item thus last found item
set "_item_Last=%%~H"
rem show every found item
echo .exe found %%~H
)
echo(---
rem show setting found
set _item
echo(---
if defined _itemFirst (
echo success: "%_checkPath%"
rem commands are merely ECHOed and (my test data) commented up
rem use found items (choose any)
rem ECHO "%_itemFirst%" -jar post.jar
rem ECHO "%_item_Last%" -jar post.jar
) else (
echo NOT FOUND "%_checkPath%"
)
Above code snippet is richly commented where necessary for better understanding. Output shows both variants:
==> D:\bat\SO\38281447.bat XXX
_checkPath=C:\Program Files*\Microsoft SQL Server\1*\LocalDB\Binn\sqlservrXXX.exe
---
dir /B /S "C:\Program Files*\Microsoft SQL Server\1*\LocalDB\Binn\sqlservrXXX.exe"
The filename, directory name or volume label syntax is incorrect.
---
---
Environment variable _item not defined
---
NOT FOUND "C:\Program Files*\Microsoft SQL Server\1*\LocalDB\Binn\sqlservrXXX.exe"
==> D:\bat\SO\38281447.bat
_checkPath=C:\Program Files*\Microsoft SQL Server\1*\LocalDB\Binn\sqlservr.exe
---
dir /B /S "C:\Program Files*\Microsoft SQL Server\1*\LocalDB\Binn\sqlservr.exe"
The filename, directory name or volume label syntax is incorrect.
---
.exe found C:\Program Files\Microsoft SQL Server\100\LocalDB\Binn\sqlservr.exe
.exe found C:\Program Files\Microsoft SQL Server\110\LocalDB\Binn\sqlservr.exe
.exe found C:\Program Files\Microsoft SQL Server\120\LocalDB\Binn\sqlservr.exe
---
_itemFirst=C:\Program Files\Microsoft SQL Server\100\LocalDB\Binn\sqlservr.exe
_item_Last=C:\Program Files\Microsoft SQL Server\120\LocalDB\Binn\sqlservr.exe
---
success: "C:\Program Files*\Microsoft SQL Server\1*\LocalDB\Binn\sqlservr.exe"
==>

Java Version in a batch file

My question, is extremely similar to the following SO question: How to get Java Version from batch script?
In fact, it did almost solve my problem. The only difference is that I've to check the Java version based on %JAVA_HOME%, which the user is free to modify. The issue that I'm facing is with this code:
#ECHO OFF
SETLOCAL enableextensions enabledelayedexpansion
IF "%JAVA_HOME%"=="" (
#ECHO Please set JAVA_HOME environment variable
EXIT /B
)
#echo "%JAVA_HOME%"
REM Checking JAVA_VERSION
SET JAVA_VERSION=
FOR /f "tokens=3" %%g in ('"%JAVA_HOME%"\bin\java -version 2^>^&1 ^| findstr /i "version"') do (
SET "JAVA_VERSION=%%g"
)
%JAVA_HOME%% in my system points to "C:\Program Files\jdk1.7.0_25" (notice the space in the path)
Even with the quotes, I get the following error in command line:
'C:\Program' is not recognized as an internal or external command,
operable program or batch file.
Any idea as to how to solve this problem? (The comments to the aforementioned article also mentions this issue). I'm working on a Windows 7 machine
FOR /f "tokens=3" %%g in ('"%JAVA_HOME%\bin\java" -version 2^>^&1 ^| findstr /i "version"') do (
SET "JAVA_VERSION=%%g"
)
Edit the %JAVA_HOME% Variable into:
C:\"Program Files"\jdk1.7.0_25
if you want it automated, type
set %JAVA_HOME%=C:\"Program Files"\jdk1.7.0_25
REASON WHY:
The batch file does not accept the quotes; It is identifying them as a single file. So it attempts to find "C:\Program Files\jdk1.7.0_25" NOT as a folder path, but as a folder NAME in your root folder. If you type in
C:\"Program Files"\jdk1.7.0.25 it identifies that "Program Files" is a single file. If there are no redirection operators, It would think that the path would be like this;
C:\Program\Files\jdk1.7.0_25. It worked for me; It should probably work for you.
Hope that helped
-SonorousTwo
I had a similar problem, take a look at my QA: How to get Java version in a batch script subroutine?
From my answer:
It seems that piping the output to findstr was stripping the quotes for some reason.
I managed to fix the problem without Epic_Tonic's workaround (which would be very difficult to do with a path as a parameter).
This should work in your case:
set first=1
for /f "tokens=3" %%g in ('"%JAVA_HOME%\bin\java" -version 2^>^&1') do (
if !first!==1 echo %%~g
set first=0
)
Note: first is for only searching the first line of java -version's output (reference).

How to test if a path is a file or directory in Windows batch file?

I searched here, found someone using this
set is_dir=0
for %%i in ("%~1") do if exist "%%~si"\nul set is_dir=1
but didn't work, when %1==c:\this is a file with spaces.csproj, the test still success, which means it will still be treated as a folder!!!
anyone knows the answer, i guess this is a very common problem and Windows has existed for many many years, it should have a very simple solution....
I know the if exist path\nul test for a folder used to work on MS-DOS. I don't know if it was broken with the introduction of long file names.
I knew that if exist "long path\nul" does not work on Windows batch. I did not realize until today that if exist path\nul works on Vista and beyond as long as path is in the short 8.3 form.
The original code appears to work on Vista. It seems like it should work on XP as well, but I believe the following XP bug is getting in the way: Batch parameter %~s1 gives incorrect 8.3 short name.
The original code does not need the FOR loop, it could simply use %~s1
Here is a variation that fully classifies a path as INVALID, FILE or FOLDER. It works on Vista, but does NOT work on XP because of the %~s1 bug. I'm not sure how it performs on MS-DOS.
EDIT 2015-12-08: There are a number of Windows situations where this fails
#echo off
if not exist "%~1" ( set "type=INVALID" ) else if exist %~s1\nul ( set "type=FOLDER" ) else ( set "type=FILE" )
#echo "%~1" = %type%
I believe this variation will work with nearly all versions of Microsoft batch, including MS-DOS and XP. (it obviously won't work on early versions of DOS that don't support PUSHD)
#echo off
if exist "%~1" (2>nul pushd "%~1" && (popd&set "type=FOLDER") || set "type=FILE" ) else set "type=INVALID"
echo "%~1" = %type%
UPDATE 2014-12-26
I'm pretty sure the following will work on all versions of Windows from XP onward, but I have only tested on Win 7.
Edit 2015-12-08: This can fail on network drives because the folder test can falsely report a file as a folder
#echo off
if exist %1\ (
echo %1 is a folder
) else if exist %1 (
echo %1 is a file
) else (
echo %1 does not exist
)
UPDATE 2015-12-08
Finally - a test that truly should work on any Windows version from XP onward, including with network drives and UNC paths
for /f "tokens=1,2 delims=d" %%A in ("-%~a1") do if "%%B" neq "" (
echo %1 is a folder
) else if "%%A" neq "-" (
echo %1 is a file
) else (
echo %1 does not exist
)
Note - This technique is intended to be used for a path without any wildcards (a single specific file or folder). If the provided path includes one or more wildcards, then it provides the result for the first file or folder that the file system encounters. Identical directory structures may give different sort order results depending on the underlying file system (FAT32, NTFS, etc.)
I just tried in this way. Hope this helps.
#ECHO OFF
SET CURR_DIR=%CD%
SET IS_DIR=0
CD %1%
IF "%ERRORLEVEL%"=="0" SET IS_DIR=1
CD %CURR_DIR%
ECHO IS DIRECTORY %IS_DIR%
Output:
D:\Work\Stand alone Java classes>test.bat D:\Work\Training
IS DIRECTORY 1
D:\Work\Stand alone Java classes>test.bat D:\Work\Training\SRT.txt
The directory name is invalid.
IS DIRECTORY 0
The /ad option for "dir" command lists folders, /b option for bare. Assuming you have checks for the existence of file in place, use:
dir /ad /b ChangeThisToYourFilename 1> NUL 2> NUL
if %ERRORLEVEL% EQU 0 (
echo is a file
) else (
echo is NOT a file
)
For a 1 liner:
dir /a:d /b C:\Windows 2>&1 | findstr /i /n /c:"File Not Found">nul && (#echo. Im a file) || (#echo. Im a folder)
e.g. change C:\Windows to C:\Windows\Notepad.exe
-Sorry Arun, dbenham, didn't read yours! Same as..
Previously, I used the "\nul" method, but for a long time now, I have used "\*" to test if an existing filespec is a folder or a file. As far as I know, it works on all versions of Windows, from Windows 95 (and perhaps earlier versions) through all current Windows versions.
So, as with other methods, first test if the file exists. Then, to see if it's a "Folder", test it with: if exist "%fspec%\*":
if not exist "%fspec%" goto :NotExistOrInvalid
rem "%fspec%" is "Valid" and is either a "Folder", or a "File".
if exist "%fspec%\*" goto :IsValidAndIsAFolder
rem "%fspec%" is a "File" (a "Regular File" or a Shortcut/Link).
goto :IsValidAndIsAFile
For example:
set "fspec=XYZ:%perlpath%"
if not exist "%fspec%" echo "%fspec%": Invalid or not found && rem Invalid, goto :NotExistOrInvalid
set "fspec=%perlpath%"
if not exist "%fspec%" echo "%fspec%": Invalid or not found && rem goto :NotExistOrInvalid
rem "%fspec%" Is a "Valid" filespec and is either a "Folder", or a "File".
if exist "%fspec%\*" (echo "%fspec%" is a "Folder".) else echo "%fspec%" is a "File".
set "fspec=%perlpath%\perl.exe"
if not exist "%fspec%" echo "%fspec%": Invalid or not found && rem Invalid, goto :NotExistOrInvalid
rem "%fspec%" Is a "Valid" filespec and is either a "Folder", or a "File".
if exist "%fspec%\*" (echo "%fspec%" is a "Folder".) else echo "%fspec%" is a "File".
The output for this is:
"XYZ:F:\usr\perl\bin": Invalid or not found
"F:\usr\perl\bin" is a "Folder".
"F:\usr\perl\bin\perl.exe" is a "File".
This solution combines the file attribute parameter extension (%~a1) with variable substring extraction (%variable:~0,1%):
#ECHO OFF
CALL :is_directory C:\Windows
CALL :is_directory C:\MinGW\share\doc\mingw-get\README
CALL :is_directory C:\$Recycle.Bin
CALL :is_directory "C:\Documents and Settings"
CALL :is_directory "%LOGONSERVER%\C$\Users\All Users"
GOTO :EOF
:is_directory
SETLOCAL
SET file_attribute=%~a1
IF "%file_attribute:~0,1%"=="d" (
ECHO %file_attribute% %1 is a directory
) ELSE (
ECHO %file_attribute% %1 is NOT a directory
)
ENDLOCAL
GOTO :EOF
Output:
d-------- C:\Windows is a directory
--a------ C:\MinGW\share\doc\mingw-get\README is NOT a directory
d--hs---- C:\$Recycle.Bin is a directory
d--hs---l "C:\Documents and Settings" is a directory
d--hs---l "\\MYCOMPUTER\C$\Users\All Users" is a directory

identify if java cannot be executed in windows batch script

I wrote the below batch script which asks for a JAVA_HOME path if its not present in environment, and then it verifies the java version. but before identifying java version it should also check whether java is present in the path (can be executed) or not. Please help me figure out if java -version can be executed or not and display proper message
#echo off
setlocal
set VERSION5="1.5"
IF "%JAVA_HOME%" == "" (
echo Enter path to JAVA_HOME:
set /p JAVA_HOME=
goto check_java_version
) ELSE (
echo Using %JAVA_HOME%
goto check_java_version
)
:check_java_version
for /f "tokens=3" %%g in ('%JAVA_HOME%\jre\bin\java -version 2^>^&1 ^| findstr /i "version"') do (
set JAVAVER=%%g
)
set JAVAVER=%JAVAVER:"=%
set JAVAVER=%JAVAVER:java version =%
for /f "delims=. tokens=1-3" %%v in ("%JAVAVER%") do (
set VER=%%w
)
if not "%VER%" GEQ "5" goto wrong_version
set JAVA_BIN=%JAVA_HOME%\jre\bin
goto correct_java_version
:correct_java_version
REM echo JAVA Version is ok.
set JAVA_LIB=%cd%/lib
%JAVA_BIN%/java -cp %JAVA_LIB%/csm-runtime-1.0.jar;%JAVA_LIB%/groovy-all-1.8.1.jar;%JAVA_LIB%/commons-beanutils-1.8.3.jar;%JAVA_LIB%/csm-dbutil-1.0.jar;%JAVA_LIB%/commons-exec-1.1.jar;%JAVA_LIB%/log4j-1.2.8.jar;%JAVA_LIB%/commons-cli-1.2.jar -Dlog4j.configuration=com/ABC/csm/log4j.xml -Dendorsed_plugins_dir=./plugins com.ABC.csm.CSMMain %*
goto end_java_version
:wrong_version
echo Current JDK Version %VER%
echo Expected JDK %VERSION5% or greater. Please fix your SSATOP and try again.
goto end_java_version
:no_java
echo No JDK found in %JAVA_HOME%.
goto wrong_version
:end_java_version
endlocal
1 of the examples of invalid condition would be, instead of providing JAVA_HOME i.e., e:\csm\java I gave it as e:\csm\java\jre\bin which in this case should display proper error message that please provide a JAVA_HOME path
To check the existence of a program in the PATH, windows batch provides the ~%PATH: option of the SET command. See HELP CALL or HELP FOR.
Use this piece of code as a starting point.
:ProgInPath
set PROG=%~$PATH:1
goto :eof
and use it like this
call :ProgInPath java.exe
IF "%PROG%" == "" (
echo Java.exe not found
) else (
echo. %PROG%
)
in this example, if java.exe is in the PATH, it echoes its complete filespec.
I used the below snippet and it solved my problem
:check_java_existence
IF EXIST %JAVA_HOME%\jre\bin\java.exe (
echo java exists
) ELSE (
echo java does not exists
)

Resources