That one line has a lot of functionality in it. An plain-English summary would go something like this:
- Ask Java what version it is. This gives multiple pieces of information.
- Find the line in Java's output that contains "version".
- Find the third component on that line.
- Echo that as output, and also set the JAVAVER environment variable to that value.
Let's break it apart.
for /f "tokens=1-3" %%g in ('java -version 2^>^&1 ^| findstr /i "version"') do ( @echo Debug Output: %%g set JAVAVER=%%g )
I'll start with the innermost piece: 'java -version 2^>^&1 ^| findstr /i "version"'
The batch file tells Windows to run this, and then the batch file will do something with the result.
The carets (^
) serve to tell the batch file to treat the following characters literally. Otherwise, the batch file would attempt to interpret them and treat them as instructions or modifiers to the batch file itself. Instead, we want the batch file to just pass them along "as-is". So, the batch file tells Windows to run this:
'java -version 2>&1 | findstr /i "version"'
java
- run java.exe
, wherever it is found in the Path
-version
- tell java.exe
to print version information and exit
2>&1
- redirect any errors to the same place as standard output (Rob van der Woude has a great page about redirection) -- you need this because Java sends its version information to the standard error stream instead of to the standard output stream -- see this Q&A on StackOverflow -- this makes it send the version information to the standard output stream instead, so it can eventually end up being seen by findstr
|
- send the results so far to the next program -- findstr
findstr
- search for a string in the input, which is the output of the java -version 2>&1
command
/i
- tell findstr
to do a case-insensitive search
"version"
- tell findstr
what text to search for
Typical output of java -version
will look like this:
java version "1.8.0_92"
Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)
And then after passing it through findstr
, you be left with only the line that contains "version":
java version "1.8.0_92"
Next, let's look at the for /f
piece. for /f … in …
will look at the result of the command that follows "in" and process it. Your first and third examples have different values for the tokens=…
part, so something may have been lost in the copying and pasting. In any case, the tokens=…
part tells the for /f
command which parts (aka tokens) of the line being processed to care about. By default, a space or a tab indicates a new token. So a parameter of tokens=3
would tell for /f
to look at the third piece of the line, which is "1.8.0_92"
. The %%g
option tells for /f
to store what it finds in variable %g
. (The extra %
is needed because you are running this from a batch file. If you ran it directly at a command prompt, you'd only need a single %
.)
So far, if you use tokens=3
, you'll have "1.8.0_92"
stored in the %g
variable. (If you used tokens=1-3
instead, you'll have "java"
in %g
, version
in %h
, and "1.8.0_92"
in %i
. The for /f
command starts shoving tokens into variables starting with the variable you specify, and incrementing through the alphabet.)
Then, the do
portion of the line tells what command you want executed for each thing the for /f
command comes up with. In this case, it does two things:
@echo Debug Output: %%g
- print "Debug Output:" to the standard out, followed by the value of the %g
variable, which we saw earlier is "1.8.0_92"
.
set JAVAVER=%%g
- set the value of the JAVAVER
environment variable to whatever is in the %g
variable.
(Rob van der Woude also has a great page explaining the for/f command.)
When you took out the findstr
part in one of your experiments, and used tokens=3
, you saw output indicating that the for /f
command grabbed the third token on each line of Java's version information, highlighted here in bold:
java version "1.8.0_92"
Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)
And that experiment would also have set the JAVAVER environment variable to each one of those strings, so it would end up with the last one -- 64-bit
.