I already have a small script in perl to do reverse lookup, but it is not portable unless the other machine also has perl installed. I want a script that can run on colleagues machines seamlessly and also can be converted into a custom command (by updating PATH & PATHEXT environment variables). The script file must be portable and available to non admin users.
Batch script seems to fit this purpose, but I cannot figure out how to call the gethostbyaddr API. I suppose VBScript is also an option and open to that.
gethostbyaddr API
Here's two batch scripts. Hopefully at least one can help.
#ECHO OFF
::Lookup.bat
::http://www.computing.net/answers/programming/ip-by-hostname/25313.html
::Takes input file of hostnames and creates csv file with hostnames and IP addresses.
::Gets IP's using nslookup
:: Output in file hostnames.csv in current folder
if "%1"=="" goto :Syntax
SET SCRIPTPATH=%~p0
CD %SCRIPTPATH%
del hostnames.csv
for /f %%e in (%1) do call :LOOKUP %%e
echo Done!!!
goto :EOF
:LOOKUP
SET HOST1=%1
FOR /F "skip=4 tokens=2 delims=:" %%A IN ('2^>NUL nslookup %1') DO ( ECHO %1,%%A>>%SCRIPTPATH%hostnames.csv )
GOTO :EOF
:Syntax
echo.
echo Syntax:
echo.
echo %0 ^<FileName^>
echo.
echo where ^<FileName^> is a file containing a list of hostnames.
echo.
echo The batch file will return the results to file hostnames.csv in current folder
goto :EOF
#echo off
::gethostname.bat
::Takes input file of IP addresses and creates csv file with IP address and hostnames.
::Gets hostnames using netBIOS, which is usually accurate. If no info avail from
::netBIOS, then use nslookup. Plenty of debug statements in screen output. :)
:: Output in file C:\TEMP\ip-resolved.csv
if "%1"=="" goto :Syntax
SET SCRIPTPATH=%~p0
CD %SCRIPTPATH%
echo ip,hostname,power>C:\TEMP\ip-resolved.csv
for /f %%e in (%1) do call :PING-NBT %%e
echo Done!!!
goto :EOF
:PING-NBT
set ipaddress=%1
set host1=
echo.
echo ***Pinging %ipaddress%
SET ON=0
PING -n 1 %1 | find /i "Reply from" >nul && SET ON=1
echo Just parsed ping reply... host is %ON%
REM Next line skips netBIOS check if host is offline
IF "%ON%"=="0" GOTO :LOOKUP %ipaddress% %ON%
echo Proceeding to nbtstat with host %on%
REM The next lines check netBIOS name.
echo nbt1-start
for /f %%i in ('nbtstat -a %1^|find "<20>"') do #set host1=%%i
echo nbt=%host1% power=%ON%
REM If there isn't a NetBIOS name, then skips to nslookup section.
REM echo %2
if "%host1%"=="" goto :LOOKUP %1 %ON%
ECHO %ipaddress%,%host1%,%ON% >> C:\TEMP\ip-resolved.csv
echo nbt2-end
goto :EOF
:LOOKUP
echo nslookup1-start
for /f "tokens=2" %%i in ('nslookup %1^|find "Name:"') do #set host1=%%i
echo nslookup=%host1% power=%2
REM Next line=if host var
rem if not "%host1%"=="%1" goto :EOF
ECHO %ipaddress%,%host1%,%2 >>C:\TEMP\ip-resolved.csv
set host1=
echo nslookup2-end
goto :EOF
:Syntax
echo.
echo Syntax:
echo.
echo %0 ^<FileName^>
echo.
echo where ^<FileName^> is a file containing a list of IP addresses to
echo which we need the hostname.
echo.
echo The batch file will return the results via a file
echo C:\TEMP\ip-resolved.csv
goto :EOF
Related
I want to make a bat file that list all of the files in a specific directory, and add numbers at the beginning of the every one of the listed items. This numbers need to be a selectable options.
Example:
I have a folder with 5 files in it, aaa.exe, bbb.exe, ccc.exe, ddd.exe, eee.exe. When i run bat file i need to see
aaa.exe
bbb.exe
ccc.exe
ddd.exe
eee.exe
So now if i wana run 5-th exe i need to press 5, than press enter and that 5th exe will now start.
I allredy find how to list all of the items in folder with this code
REM -start "c:\windows\system32" notepad.exe
for /r %%i in (*) do echo %%i
pause
exit
but i can't figure out how to add numbers in front of the text and make that numbers to be a selectable options.
Edit---
Now im getting
ERROR: Duplicate choices are not allowed. running '""' is not
recognized as an internal or external command, operable program or
batch file.
when i'm trying to run this loop for a second time.
This is code that i wrote:
#ECHO OFF
setlocal enabledelayedexpansion
REM ---Prompt part
:choise
SET /P AREYOUSURE=Install programs (Y/[N])?
IF /I "%AREYOUSURE%" EQU "Y" GOTO :chooseInstall
IF /I "%AREYOUSURE%" EQU "N" GOTO :nope
REM --Cheking for Y or N
GOTO :choise
:nope
echo "Ok. Have a nice daty / night"
pause
exit
:chooseInstall
echo Wich program do you wana install ?
echo.
echo 1. 7Zip
echo 2. CPU Z
echo.
SET /P AREYOUSURE=Choosing:
IF /I "%AREYOUSURE%" EQU "1" set "pathToSoft=C:\Users\usr\Desktop\hello"
IF /I "%AREYOUSURE%" EQU "2" set "pathToSoft=C:\Users\usr\Desktop\bye"
echo.
echo.
echo %pathToSoft%
echo.
echo.
REM ---Installs
echo "Wich file to install"
cd %pathToSoft%
echo.
echo.
REM --Loops that scan files
set /A counter=0
for /R %%i in (*) do (
if not "%%~nxi" == "%~nx0" (
set /A counter+=1
echo !counter!: %%~nxi
set exe[!counter!]=%%i
set choice=!choice!!counter!
)
)
if %counter% LSS 10 (
choice /C %choice% /M "Choose: "
set EXENUM=!ERRORLEVEL!
) else set /P EXENUM="enter exe number: "
set EXECUTABLE=!exe[%EXENUM%]!
echo running %EXECUTABLE%
call "%EXECUTABLE%"
echo.
echo.
echo.
:installmore
SET /P INSTALLMORE=Do you wana install somthing else (Y/[N])?
IF /I "%INSTALLMORE%" EQU "Y" GOTO :chooseInstall
IF /I "%INSTALLMORE%" EQU "N" GOTO :nope
count the executables and associate them with the counter, creating kind of "array" variables (filter out the current batch script)
build the choice list at the same time
after the loop, use choice if no more than 9 choices, else use a classical interactive set
retrieve the user selection and call the executable/batch file
(you have to enable delayedexpansion to be able to use % and ! env. var separators & instant evaluation within the loop)
can be done like this:
#echo off
setlocal enabledelayedexpansion
set /A counter=0
set choice=
for /R %%i in (*) do (
if not "%%~nxi" == "%~nx0" (
set /A counter+=1
echo !counter!: %%~nxi
set exe[!counter!]=%%i
set choice=!choice!!counter!
)
)
if %counter% LSS 10 (
choice /C %choice% /M "type exe number"
set EXENUM=!ERRORLEVEL!
) else set /P EXENUM="enter exe number: "
set EXECUTABLE=!exe[%EXENUM%]!
echo running %EXECUTABLE%
call "%EXECUTABLE%"
I want to check if a hostname exists on my PC (ie found in hosts file under C:\Windows\System32\drivers\etc).
Is there a way to find if it exist using a batch command or some other way?
Give a try for this batch file with some extra info :
#echo off
set "SearchString=localhost"
set "LogFile=%userprofile%\Desktop\LogFile.txt"
set "hostspath=%windir%\System32\drivers\etc\hosts"
(
Echo **************************** General info ****************************
Echo Running under: %username% on profile: %userprofile%
Echo Computer name: %computername%
Echo Operating System:
wmic os get caption | findstr /v /r /c:"^$" /c:"^Caption"
Echo Boot Mode:
wmic COMPUTERSYSTEM GET BootupState | find "boot"
Echo Antivirus software installed:
wmic /Node:localhost /Namespace:\\root\SecurityCenter2 Path AntiVirusProduct Get displayName | findstr /v /r /c:"^$" /c:"displayName"
Echo Executed on: %date% # %time%
Echo ********************* Hosts' File Contents with the string "%SearchString%" ************************
)>"%LogFile%"
for /f "delims=" %%a in ('Type "%hostspath%" ^| find /I "%SearchString%"') Do (
echo %%a >> "%LogFile%"
)
Start "" "%LogFile%"
Easier and more robust solution
url.bat:
#echo off
set url=%1
ping -n 1 %url% > nul 2> nul
if "%errorlevel%"=="0" (
echo %url% exists
) else (
echo %url% does not exist
)
Test
> url.bat google.com
google.com exists
> url.bat google.commmmmm
google.commmmmm does not exist
What you possibly can do is pinging the hostname you are looking for and then check for certain strings, that will show you if the hostname could be found or not. Would look like this (I guess):
#echo off
setlocal EnableDelayedExpansion
set /p input= "Hostname"
set hostexists=yes
For /f "tokens=1,2" %%a in ('ping -n 1 !input!') do (
if "x%%a"=="xFOO" if "x%%b"=="xBAR" set hostexists=no
)
If "x!hostexists!"=="xno" (
echo. "Does not exist"
) ELSE (
echo. "Does exist"
Pause
Basic thought is that when you try to ping a hostname that is not available, you will get a specific output from the commandline. Try it yourself: Open the cmd.exe (Hit the Windows-Button +R and type cmd) and in the commandline write ping foobar and wait a bit. You should get a message like: Ping-Request could not find "foobar" [...]. You take the first two words and put them into the code: 1st word to FOO and 2nd to BAR.
The program will look into the output of the ping command and place the first two words (=tokens) in %%a and %%b checking if they are equal to the desired words, marking the host does not exist.
I hope this will help :) Not sure if that is what you wanted :D
Greetings
geisterfurz007
I am writing a batch file. part of the program will compare the list of files in a 'source' folder. With the contents of a list in a text file.
I loop through each file in the folder, and search for its filename in the text file using FINDSTR
Everything works until there is a filename in the source folder that doesnt exist in the text file.
the findstr code:
for /f %%o in ('findstr %name% old.txt') do (
echo o=%%o >> result.txt
if %%o==%name% (
echo %name% exists
) ELSE (
echo %name% does not exists
)
)
Again, the problem occurs when FINDSTR searches for a filename that is not in the text file.
when it reaches that point it outputs the variable %%o as being '%o' and echos nothing. So it sends nothing to the results.txt.
This doesnt trigger an ERRORLEVEL change but also will not echo anything. I have tried outputing the errorlevels but they are also empty. I just dont understand what FINDSTR is doing in this instance.
the FULL batch file: (its my first one. forgive any mistakes)
::return the raw (/b) list of files
FORFILES /p %~dp0source\ /s /m "*.cr2" /C "cmd /c echo #path" > new.txt
::pull file path for each file and send to subroutine
for /f %%n in ('FORFILES /p %~dp0source\ /s /m "*.cr2" /C "cmd /c echo #path"') do (
call :dequote %%n
)
::subroutine for removing quotes
::and returning the filename, extension, and path
:dequote
set fullPath=%~f1
set fileName=%~n1
set fileExt=%~x1
set filePath=%~dp1
set name=%fileName%& set npath=%filePath%& set ext=%fileExt%& set fpath=%fullPath%
echo %fpath%
echo %npath%
echo %name%
echo %ext%
for /f %%o in ('findstr %name% old.txt') do (
echo o=%%o >> result.txt
if %%o==%name% (
echo %name% exists
) ELSE (
echo %name% does not exists
)
)
This only happens on the last filename sent to findstr. Any suggestions or direction would be very appreciated. Ive tried and read everything I can get my hands on.
Thank You for your time.
UPDATE: 9-9-15
Here is the working final batch file i created using the help on this page. It creates a hotfolder that will edit any new files added to it until you stop the script from running:
:start
:: return the raw (/b) list of files and full path to source text
FORFILES /p %~dp0source\ /s /m "*.cr2" /C "cmd /c echo #path" > source.txt
IF %ERRORLEVEL% EQU 1 goto :start
::join new and old data, return only what is shared in common (/g)
findstr /I /L /G:"source.txt" "output.txt" > found.txt
IF %ERRORLEVEL% EQU 1 copy /y source.txt notFound.txt
::join found file names and source filenames, return those that do not have a match
findstr /I /L /V /G:"found.txt" "source.txt" >> notFound.txt
IF %ERRORLEVEL% EQU 2 echo error no match
::for each line of notFound.txt, dequote and break apart
for /f %%n in (notFound.txt) do (
echo n=%%n
call :dequote %%n
)
:dequote
set fullPath=%~f1
set fileName=%~n1
set fileExt=%~x1
set filePath=%~dp1
set name=%fileName%& set npath=%filePath%& set ext=%fileExt%& set fpath=%fullPath%
echo %fpath%
echo %npath%
echo %name%
echo %ext%
cd %nPath%
if NOT [%1]==[] (
echo converted %name%
convert -negate -density 600 -colorspace gray flatField.cr2 %name%%ext% -compose Divide -composite %name%.tif
move %name%.tif %~dp0output
cd %~dp0
del notFound.txt
copy /y source.txt output.txt
) ELSE (
echo end of batch else
cd %~dp0
)
Loop variables must be referenced with %% in a batch file because percent sign has a special meaning and must be therefore escaped with another percent sign in a batch file to specify it literally. This is the reason why on running the batch file with echo on in a command prompt window results in getting %%o in the batch file displayed as %o on execution.
Command FOR as used in
for /f %%o in ('findstr %name% old.txt') do
processes the output written to stdout by the called command findstr. But findstr does not write anything to standard output when it searched for one or more strings in a file and could not find any matching string in any line of the file.
So command for can't process anything and therefore none of the commands after do are processed at all in this case.
Assuming the list file contains only file names without path, the following commented batch file can be used to get with 1 execution of command dir and just 1 or 2 executions of console application findstr the two lists containing the file names in folder being found and being not found in the list file. The batch file is written for not producing empty files.
#echo off
setlocal
set "ListFile=C:\Temp\List.txt"
if not exist "%ListFile%" goto NoListFile
set "SourceFolder=C:\Temp\Test"
if not exist "%SourceFolder%\*" goto NoSourceFolder
set "AllFileNames=%TEMP%\AllFileNames.txt"
set "FoundFileNames=%TEMP%\FoundFileNames.txt"
set "NotFoundFileNames=%TEMP%\NotFoundFileNames.txt"
rem Get alphabetic list of files in source folder without path.
dir /A /B /ON "%SourceFolder%" >"%AllFileNames%"
rem Find all file names in list file with a case-insensitive
rem search matching completely a file name in list file and
rem output the found file names to another list file.
%SystemRoot%\system32\findstr.exe /I /L /X "/G:%AllFileNames%" "%ListFile%" >"%FoundFileNames%"
if errorlevel 1 goto NoFileNameFound
rem Find all file names with a case-insensitive search found
rem before in all file names list and output the lines not
rem containing one of the file names to one more list file.
%SystemRoot%\system32\findstr.exe /I /L /V "/G:%FoundFileNames%" "%AllFileNames%" >"%NotFoundFileNames%"
if errorlevel 1 goto AllFileNamesFound
rem Some file names are found in list file and others not.
del "%AllFileNames%"
goto :EndBatch
:NoFileNameFound
move /Y "%AllFileNames%" "%NotFoundFileNames%"
del "%FoundFileNames%"
goto EndBatch
:AllFileNamesFound
del "%AllFileNames%"
del "%NotFoundFileNames%"
goto EndBatch
:NoListFile
echo %~f0:
echo Error: No list file %ListFile%
goto EndBatch
:NoSourceFolder
echo %~f0:
echo Error: No folder %SourceFolder%
:EndBatch
endlocal
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.
del /?
dir /?
findstr /?
goto /?
if /?
move /?
set /?
This is a method to give you a list of filenames which don't exist in the file.txt
#echo off
cd /d "c:\folder\to\check"
for %%a in (*) do findstr /i "%%~nxa" "file.txt" >nul || echo "%%a" is missing
pause
It uses %%~nxa instead of %%a in case subdirectories are used at some point.
OK. My question pretty much explains itself. Is it possible to creat a batch file, that when executed will create another batch file via copy con command?
Something like:
#echo off
copy con file.bat
#echo off
echo hallo
exit
^Z
start file.bat
The only problem I encountered trying to do this, was that you manualy need to hit Enter after ^Z, and I cannot find any kind of cmd command to replicate that.
Does anyone know if such a thing is possible? Or is there any other way for a batch file to re-create another batch file or itself?
Thank you.
It may be possible to issue an escape code for ^Z and do it with copy con but why would you?
Just just normal redirection of the echo command.
Like this:
#echo off
echo Generating batch file
echo echo Hello world > hello.bat
echo Now running batch file
echo ----------
call hello.bat
echo ----------
echo Ta-da!
There are multiple ways to create a Batch file from inside another one. The methods that use echo batch code requires to escape the special characters that may appear in the "batch code". There are other methods that consist in read lines from the Batch file itself and then output such lines to the created file; in this case, the lines may have pure Batch code even if they contains special characters.
The method you used in your example is similiar to Unix heredoc feature, that is:
tr a-z A-Z << END_TEXT
one two three
uno dos tres
END_TEXT
There are several ways to simulate a "Unix heredoc" in Batch; for example this one:
#echo off
rem Definition of heredoc macro
setlocal DisableDelayedExpansion
set LF=^
% Don't remove this line 1/2 %
% Don't remove this line 2/2 %
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
set heredoc=for %%n in (1 2) do if %%n==2 (%\n%
for /F "tokens=1,2" %%a in ("!argv!") do (%\n%
if "%%b" equ "" (call :heredoc %%a) else call :heredoc %%a^>%%b%\n%
endlocal ^& goto %%a%\n%
)%\n%
) else setlocal EnableDelayedExpansion ^& set argv=
rem Heredoc syntax:
rem
rem %%heredoc%% :uniqueLabel [outfile]
rem contents
rem contents
rem ...
rem :uniqueLabel
rem For example:
%heredoc% :endBatch file.bat
#echo off
echo hallo
exit /B
:endBatch
echo Calling created file:
call file.bat
echo Return from created file
goto :EOF
rem Definition of heredoc subroutine
:heredoc label
set "skip="
for /F "delims=:" %%a in ('findstr /N "%1" "%~F0"') do (
if not defined skip (set skip=%%a) else set /A lines=%%a-skip-1
)
for /F "skip=%skip% delims=" %%a in ('findstr /N "^" "%~F0"') do (
set "line=%%a"
echo(!line:*:=!
set /A lines-=1
if !lines! == 0 exit /B
)
exit /B
Isn't it better to do it like this? Maybe I don't know what you mean, but I think this can help you:
#echo off
>newbatch.bat (
echo #echo off
echo echo It works!
echo echo Hope it helped you :)
echo pause >nul
)
run newbatch.bat
I have written a batch file which will get sql server named instance(mssqlserver\india) and the disk free space.
The content on file looks like this:
mssqlserver\India,D,20
mssqlserver\India,C,30
Now I have written a batch file to generate a html report based on the text file Result.txt. But my batch script is picking mssqlserver\India as a system location and is popping message for every entry in the text file, its moving to the next variable after I press enter key.
I want to ignore this message without any user interaction. Below is the script i am using:
#ECHO off
setlocal EnableDelayedExpansion
SETLOCAL
cd C:\Users
goto head >nul
:head
FOR /F "tokens=1-6 delims=," %%G IN (Result.txt) DO (
%%G%%H%%I
set temphost1=%%G
set temphost2=%%H
set temphost3=%%I
call :stripquotes %temphost1% %temphost2% %temphost3% >NUL
)
goto :end
:stripquotes
echo ^<tr bgcolor="#90EE90"^>^<td^>^%temphost1%^</td^>^<td^>^%temphost2%^</td^>^<td^>^%temphost3%^</td^>^</tr^>^ >> C:\Users\Report.html
:END
CLS
ECHO COMPLETED
PAUSE
With some #rem commented changes, next script could work:
#ECHO off
#rem EnableDelayedExpansion not applied in the code
#rem use enableextensions in the next line
setlocal EnableDelayedExpansion
#rem superabundant SETLOCAL
cd C:\Users
#rem Why "goto head >nul" as GOTO does not produce any output?
#rem And why next "goto head" at all?
goto head >nul
:head
FOR /F "tokens=1-6 delims=," %%G IN (Result.txt) DO (
#rem this caused the error message %%G%%H%%I
set temphost1=%%G
set temphost2=%%H
set temphost3=%%I
call :stripquotes
#rem this were superabundant and harmful %temphost1% %temphost2% %temphost3% >NUL
)
goto :end
:stripquotes
#rem some superfluous `^` carets removed from next line but the last one was harmful
echo ^<tr bgcolor="#90EE90"^>^<td^>%temphost1%^</td^>^<td^>%temphost2%^</td^>^<td^>%temphost3%^</td^>^</tr^> >> C:\Users\Report.html
#rem next line to return from the :stripquotes subroutine
goto :eof
:END
CLS
ECHO COMPLETED
PAUSE