Reputation: 13
Could you please guide me how to fix my script to get the trace route results to some IP addresses?
I want to get the tracert
results for 8.8.8.8 and 8.8.4.4. I wrote the script below and it works fine:
@echo off
echo %date% %time%
SET DNS1=8.8.8.8
SET DNS2=8.8.4.4
for %%i in (%DNS1% %DNS2%) do (
echo ----------------
echo tracert to %%i
tracert -d %%i
)
echo %time%
exit
I want to add a function so that it can print host name automatically. I tried as below, but it doesn't work.
@echo off
echo %date% %time%
SET DNS1=8.8.8.8
SET DNS2=8.8.4.4
for %%i in (%DNS1% %DNS2%) do (
echo ----------------
if (%%i == 8.8.8.8 set host=Google1
%%i == 8.8.4.4 set host=Google2)
echo tracert to %host%
tracert -d %%i
)
echo %time%
exit
Could somebody please correct the code for me?
Upvotes: 1
Views: 62
Reputation: 49097
The batch file could be written like this:
@echo off
echo %DATE% %TIME%
setlocal EnableExtensions EnableDelayedExpansion
set "DNS1=8.8.8.8"
set "DNS2=8.8.4.4"
for %%i in (%DNS1% %DNS2%) do (
echo ----------------
if %%i == 8.8.8.8 set "host=Google1"
if %%i == 8.8.4.4 set "host=Google2"
echo tracert to !host!
tracert -d %%i
)
endlocal
echo %TIME%
exit /B
Windows command processor executes one command line after the other. How a command line is parsed before execution is described at How does the Windows Command Interpreter (CMD.EXE) parse scripts? What is executed finally after parsing a command line can be seen on executing a batch file without @echo off
from within a command prompt window as described at debugging a batch file.
A command block starting with (
and ending with matching )
is parsed completely by cmd.exe
before the command is executed with makes conditionally or unconditionally use of the command block. During parsing the command block all environment variable references using syntax %variable%
like %host%
are substituted by current value of the referenced environment variable. In this case %host%
is most likely replaced by an empty string before FOR is executed at all if the environment variable host
is not defined by chance on starting the batch file.
The help output on running set /?
in a command prompt window explains when and how to use delayed expansion on an IF and a FOR example. In code above delayed environment variable expansion is enabled and used to reference the current value of environment variable host
on iterations of the loop body command block on which the environment variable is defined and gets assigned a string value.
There would be also possible to use:
@echo off
echo %DATE% %TIME%
setlocal EnableExtensions DisableDelayedExpansion
set "DNS1=8.8.8.8"
set "DNS2=8.8.4.4"
for %%i in (%DNS1% %DNS2%) do (
echo ----------------
if %%i == 8.8.8.8 set "host=Google1"
if %%i == 8.8.4.4 set "host=Google2"
call echo tracert to %%host%%
tracert -d %%i
)
endlocal
echo %TIME%
exit /B
The command line call echo tracert to %%host%%
is modified during the parsing step of entire command block by Windows command processor to call echo tracert to %host%
and because of command CALL this command line is parsed a second time on each execution of the command block before ECHO command is executed resulting in printing the current value of environment variable host
to console window.
But I suggest to use this much better code:
@echo off
echo %DATE% %TIME%
echo/
setlocal EnableExtensions DisableDelayedExpansion
set "DNS1=8.8.8.8=Google1"
set "DNS2=8.8.4.4=Google2"
for /F "tokens=2* delims==" %%I in ('set DNS 2^>nul') do (
echo ----------------
echo tracert to %%J
echo %SystemRoot%\System32\tracert.exe -d %%I
)
endlocal
echo/
echo %TIME%
exit /B
One or more IP addresses and their host names are assigned to one or more environment variables starting with the string DNS
. IP address and host name are separated by an equal sign.
The command FOR runs in a separate command process started with cmd.exe /C
in background the command line:
set DNS 2>nul
Command SET outputs to handle STDOUT (standard output) all environment variables starting with DNS
sorted alphabetically with name=value
which means for this example:
DNS1=8.8.8.8=Google1
DNS2=8.8.4.4=Google2
The error message output by SET to handle STDERR (standard error) on not finding any environment variable starting with the string DNS
would be suppressed by this code by redirecting it to device NUL.
Read also the Microsoft article about Using Command Redirection Operators for an explanation of 2>nul
. The redirection operator >
must be escaped with caret character ^
on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded set
command line with using a separate command process started in background.
FOR with using option /F
captures everything output to handle STDOUT in background command process and processes this output by ignoring empty lines and lines starting with a semicolon.
The captured lines start all with DNS
and so there is definitely no line ignored as no line starts with a ;
.
FOR with using option /F
would also split each line into substrings using space/tab as delimiter with assigning just first substring to specified loop variable I
. But this line splitting behavior is not useful for this task.
For that reason the option string "tokens=2* delims=="
redefines the line splitting behavior. Now =
is used as delimiter between the strings instead of space and tab.
And instead of assigning the first =
delimited string to loop variable I
which would be the name of the environment variable, the second equal sign delimited string is assigned to loop variable I
because of tokens=2
which is the IP address.
And there is additionally assigned to next loop variable J
according to ASCII table the rest of the line after the equal sign(s) after second =
delimited string without any further string splitting on an equal sign. So the host name is assigned to loop variable J
, even on containing one or more =
as long as not containing them at beginning of host name.
This code is obviously better as the DNS
environment variables can be defined all at top of the batch file with IP address and host name and nothing must be changed on the command lines below because it simply processes from 0 to n environment variables starting with DNS
and having at least a second =
delimited substring.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
echo /?
endlocal /?
exit /?
for /?
if /?
set /?
setlocal /?
tracert /?
Upvotes: 1
Reputation: 14290
The proper use to test multiple conditions using an IF
command is used in this code. As a best practice I always use quotes around string comparisons. Also note the use of delayed expansion with the host
variable. This is required because you are creating a variable inside a parenthesized code block.
@echo off
setlocal enabledelayedexpansion
echo %date% %time%
SET DNS1=8.8.8.8
SET DNS2=8.8.4.4
for %%i in (%DNS1% %DNS2%) do (
echo ----------------
if "%%i"=="8.8.8.8" set host=Google1
if "%%i"=="8.8.4.4" set host=Google2
echo tracert to !host!
tracert -d %%i
)
echo %time%
endlocal
exit
Upvotes: 2