I'm still pretty new to batch but I wanted to try out some different functionalities within the same batch program. Essentially, I am attempting to parse through a .txt file of hostnames and ping them 1 time each, and return a pass or fail by utilizing a find query for the specific ping result. The second find query is redundant but left in. A string of "timed out" indicates that the host is down. I have been able to achieve this with this bulky code, but my actual ping statistics are no longer being written to this log file.
I'm not too familiar with the command pipeline character but it may just be incompatible for this specific use case. If I remove the piped command for the find query, it is able to write the output of the ping command just fine, but then I lose the utility of a return pass or fail value. Is this just a simple syntax error? I've tried moving the location of the actual write to file argument on the line itself but it hasn't worked. Also, why are the errorlevel values inverted (line 21)? I can't seem to return what I'm looking for.
Is there anyway I can get all these parts to play nice together? I apologize if the answer is quite obvious...
#echo off
setlocal
set hosts=temp.txt
set count=0
echo.
echo Parsing File: %hosts%
echo.
echo Start > C:\Users\___\Downloads\pingLOG.txt
for /F "tokens=*" %%i in (%hosts%) do (
set /A count=count+1
echo+
echo.
echo [+] Pinging: %%i
echo [+] Pinging: %%i >> C:\Users\___\Downloads\pingLOG.txt
echo.
ping -n 1 "%%i" | find /I "timed out" >> C:\Users\___\Downloads\pingLOG.txt
if errorlevel == 1 (
echo Pass
) else (
echo Fail
)
echo.
echo %TIME% >> C:\Users\___\Downloads\pingLOG.txt
)
echo.
echo %count% Hosts Scanned
find /c "timed out" C:\Users\___\Downloads\pingLOG.txt
echo.
pause
You can't filter the output for a certain string and expect the complete output (eliminating unwanted parts is the very reason for filtering).
To accomplish your goal, you need a temporary file (the complete output) and filter that file, so you have both variants (filtered and unfiltered) (suboptimal, but well...):
ping -n 1 "%%i" >"%temp%\temp.tmp"
find /I "timed out" "%temp%\temp.tmp" >nul && set "status=Fail" || set "status=Pass"
type "%temp%\temp.tmp" >> "C:\Users\___\Downloads\pingLOG.txt"
echo %status% >> "C:\Users\___\Downloads\pingLOG.txt"
Related
I use windows 7 pro service pack 1.
I have the following code in the post build event :
SET VAR1=BLABLA
ECHO %VAR1% > Test.txt
It wont work. In the file, i get «command echo activated» (translated from french).
Embarcadero documentation says that i can use any valid dos command in those events.
If i just use :
ECHO BLABLA > Test.txt
It works, no problem. Is this a bug or there is a problem with % character ? % is an ascii char so i dont even know what could be the problem.
ty for your help.
% is used in cmd to delimit variablenames when the value of the variable is required, hence echo %var1% > test.txt will write the current value of the environment variable var1 to the file.
If var1 is not defined at the time, it will report the echo status (Echo is on/off`.
This can be circumvented by using echo(%var1% - the ( modifies echo's behaviour to not report the echo status if the arguments are resolved to nothing.
If you want to echo a literal % then you need to escape the % with another %. cmd normally uses ^ to escape symbols with a special meaning - % is the exception; %% to echo a literal %.
BTW - the space between the string to be echoed and the redirector will be output to the file. To prevent this, use > test.txt echo %var1% Note that > creates a file anew. >> will create or append if the file already exists. The space between the redirector and the filename is optional.
However, it's important when using batch to post exactly the code that's in use.
SET VAR1=BLABLA
ECHO %VAR1% > Test.txt
will work happily.
SET VAR1 = BLABLA
ECHO %VAR1% > Test.txt
will not because this latter code sets a variable named "var1Space"
On my 10.2.1 system, I've tried the code as published.
The actual code that's executed is
SET VAR1=BLABLA&ECHO %VAR1% > Test.txt
not
SET VAR1=BLABLA
ECHO %VAR1% > Test.txt
as shown in the "Build events commands" window.
This will not work because the entire line is executed as published on the "build events" page - SET VAR1=BLABLA&ECHO %VAR1% > Test.txt which will be interpreted by cmd after cmd performs its standard parsing routine.
cmd replaces any %var% with the actual value at parse time, not at run time hence as var1 has no value when the line SET VAR1=BLABLA&ECHO %VAR1% > Test.txt is parsed, the code is executed as SET VAR1=BLABLA&ECHO > Test.txt hence the problem encountered.
To cure this, you need to use
SET VAR1=BLABLA&call ECHO %%VAR1%% > Test.txt
where cmd will execute the parsed-ECHO command in a subshell. % is the escape character for % so the subshell executes ECHO %VAR1% > Test.txt after var1 has been set.
I'd suggest you raise this as a problem with EMBT. Batch commands cannot be strung together with & without side-effects. The code entered into the "Build events commands" window should be executed without reformatting - just written to a (temporary) batch file and the batch file then executed.
No doubt the eager downvoters will support the resolution of this problem.
i use the following command to create a variable from my CPU Name:
#echo off
Rem create variable from cpu name
for /f "useback tokens=* skip=1" %%g in (`wmic cpu get name ^|findstr /i "."`) do (
set CPU_NAME=%%g
echo %CPU_NAME%
)
but the result is nothing, because there is some empty lines at end of "wmic cpu get name" command result and remove created variable
how can i solve it?
thanks a lot
Please search SO for delayed expansion.
call echo %%CPU_NAME%%
should show you the required data. This is one of several well-documented solutions.
There are some empty lines at the end of wmic cpu get name
Use findstr as follows to strip blank lines from the wmic output. You also need to use delayed expansion
Corrected batch file (test.cmd):
#echo off
setlocal enabledelayedexpansion
Rem create variable from cpu name
for /f "useback tokens=* skip=1" %%g in (`wmic cpu get name ^| findstr /r /v "^$"`) do (
set CPU_NAME=%%g
echo !CPU_NAME!
)
endlocal
Example usage:
> test
Intel(R) Core(TM) i5-2410M CPU # 2.30GHz
Further Reading
An A-Z Index of the Windows CMD command line - An excellent reference for all things Windows cmd line related.
enabledelayedexpansion - Delayed Expansion will cause variables to be expanded at execution time rather than at parse time.
findstr - Search for strings in files.
wmic - Windows Management Instrumentation Command.
There is no need to echo the result within the for loop in your case because you are only setting a single name. Just echo it later.
#Echo Off
For /F "Skip=1 Delims=" %%A In ('WMIC CPU Get Name'
) Do For /F "Delims=" %%B In ("%%A") Do Set "CPU_NAME=%%B"
Echo=%CPU_NAME%
The second For loop is intended to remove the unwanted 'empty lines' you reported.
so here is my script to loop through specific video extensions » add a manual profile » generate necessary *.bat & finally a final 'loader' batch file to execute previous *.bat files sequentially & necessary logging (this gives quiet a deal of freedom if you so want)
::==
:: gets lines into vars c1 v2 v...
#echo off
:: user input required
cd /d "d:\Trainers\out\"
setLocal EnableDelayedExpansion
dir /B /O:N | findstr ".wmv$ " >filename.txt
echo. >log.txt
:: user input required
for /f "tokens=* delims= " %%a in ('type filename.txt ^|findstr ".wmv$"') do (
set /a n+=1
echo. >file!n!.bat
set in=%in%%%a
:: user input required
set out=!in:.wmv=.mp4!
:: user input required
set v=x264 --crf 23 --level 3.1 --tune film -o "d:\Trainers\out\!in!" "d:\Trainers\out\!out!"
echo. !v!>file!n!.bat
)
dir /B /O:N | findstr ".bat$ " >x264_home.txt
for /f "tokens=* delims= " %%a in (x264_home.txt) do (
set /a n+=1
:: mtee is an external library Google it
set "z=call %%a | mtee /d/c/t/+ log.txt"
echo. !z! >> x264_home.bat
)
echo. #echo off > newFile.bat
type x264_home.bat >> newFile.bat
type newFile.bat > x264_home.bat
del newFile.bat,x264_home.txt,filename.txt
echo. pause >> x264_home.bat
echo. #echo All Operation done... >> x264_home.bat
:: user input required
move "d:\Trainers\out\*.bat" "d:\Program Files\x264_auto\test\"
:: user input required
move "d:\Trainers\out\log.txt" "d:\Program Files\x264_auto\test\"
::==
Now the above code which is fairly easy to understand (bcz its written by a noob) run perfectly & create necessary files. For instance one of the file1.bat looks like this:
x264 --crf 23 --level 3.1 --tune film --preset veryslow --deblock -2:-1 --zones 24233,25324,q=20 --acodec aac --abitrate 80 -o "d:\Trainers\out\1.wmv" "d:\Trainers\out\1.mp4"
...& the loader .bat file looks like
#echo off
call file1.bat | mtee /d/c/t/+ log.txt
call file2.bat | mtee /d/c/t/+ log.txt
call file3.bat | mtee /d/c/t/+ log.txt
#echo All Operation done...
You see this is a quiet flexible approach in that you can use special filestr » set another loop » set another profile. Furthermore every batch file can be latter edited especiialy when you heavily use --zone x264 feature
I am successful because there is no error in any output ...but its the x264.exe (provider/compiler x264GUI) throws error which it otherwise don't?
d:\Program Files\x264_auto\test>x264 --crf 23 --level 3.1 --tune film --preset
veryslow --deblock -2:-1 --zones 24233,25324,q=20 --acodec aac --abitrate 80 -o
"d:\Trainers\out\1.wmv" "d:\Trainers\out\1.mp4"
ffms [error]: could not create index
lavf [error]: could not open input file
raw [error]: raw input requires a resolution.
x264 [error]: could not open input file `d:\Trainers\out\1.mp4' via any method!
its the x264 thats the culprit perhaps a senior guide is required here
Is your x264 compiled with mp4 input support? (I believe that needs lavc/lavformat, just download precompiled x264 from x264.nl which has all extras)
Do you get the same error if you run the same command directly? (not through bat files)
If yes, does it only happen when you use zones? (if it does, then post an example of your command line as x264 bug to x264-devel mailing list)
If no, are you sure you are running the exact same x264? (perhaps there are several in different places on your system)
I recommend doing what you're doing either (a) in python with subprocess.call(...) or (b) in cygwin/bash/shell script, or . bat files are pretty much the wrong answer to any problem :) The nice thing about either of those two is that they have simple, regular escaping rules for program arguments.
I can't figure out how to get my audio extractor script working via commandline arguments on ahk. I know the command line argument is correct, as I'm able to get it working through a batch file, but I keep getting the error below. I think I'm probably doing something wrong syntactically but I just can't figure out what.
I'd really appreciate any help. Thanks.
Error: the following variable name contains an illegal character"
channels=2,samplerate=44100}:standard{access="file",mux=dummy,dst="%A_LoopField%.mp3"}
Code:
fileselectfile, File_Name, M3
SplitPath, File_Name, name
Loop, parse, name, `n
if a_index = 2
{
msgbox, %A_LoopField%
Run, "C:\Program Files\VideoLAN\VLC\vlc.exe" "-I dummy -v %File_Name% :sout=#transcode{vcodec=none,acodec=mp3,ab=128,channels=2,samplerate=44100}:standard{access="file",mux=dummy,dst="%A_LoopField%.mp3"}"
}
Here is the original batch code if you're curious about the audio extraction function I was talking about
#ECHO OFF
REM Loop through files (Recurse subfolders)
REM Syntax
REM FOR /R [[drive:]path] %%parameter IN (set) DO command
REM
REM Key
REM drive:path : The folder tree where the files are located.
REM
REM set : A set of one or more files. Wildcards must be used.
REM If (set) is a period character (.) then FOR will
REM loop through every folder.
REM
REM command : The command(s) to carry out, including any
REM command-line parameters.
REM
REM %%parameter : A replaceable parameter:
REM in a batch file use %%G (on the command line %G)
FOR /R %%G IN (*.mp3) DO (CALL :SUB_VLC "%%G")
FOR /R %%G IN (*.mp3.mp*) DO (CALL :SUB_RENAME "%%G")
GOTO :eof
:SUB_VLC
SET _firstbit=%1
SET _qt="
CALL SET _newnm=%%_firstbit:%_qt%=%%
SET _commanm=%_newnm:,=_COMMA_%
REM echo %_commanm%
ECHO Transcoding %1
REM Here's where the actual transcoding/conversion happens. The next line
REM fires off a command to VLC.exe with the relevant arguments:
CALL "C:\Program Files\VideoLAN\VLC\vlc" -I dummy -v %1 :sout=#transcode{vcodec=none,acodec=mp3,ab=128,channels=2,samplerate=44100}:standard{access="file",mux=dummy,dst="%_commanm%.mp3"} vlc://quit
REM Having no SLEEP-esque command, we have to trick DOS/Windows into pausing
REM for a bit between encode ops - To give the host OS a chance to do what it
REM needs to - Via clever use of the PING utility:
REM (Thanks to http://www.computing.net/answers/programming/dos-command-for-wait-5-seconds/11192.html for the tip! :-)
PING -n 1 -w 10000 1.1.1.1 > NUL
GOTO :eof
:SUB_RENAME
SET _origfnm=%1
SET _endbit=%_origfnm:*.mp3=%
CALL SET _newfilenm=%%_origfnm:.mp3%_endbit%=.mp3%%
SET _newfilenm=%_newfilenm:_COMMA_=,%
COPY %1 %_newfilenm%
GOTO :eof
:eof
REM My own little addition to prevent the batch window from "vanishing" without
REM trace at the end of execution, as if a critical error had occurred.
PAUSE
Have you tried without the SplitPath, File_Name, name? I got rid of the error like this, but I don't know if it produces the result you want in the end.
I found the answer. I was making syntatical errors I just didn't have the knowledge to fix myself. The new RUN statement works perfectly.
Here is the newly revised script
fileselectfile, File_Name, M3
SplitPath, File_Name, name, dir, ext, name_no_ext, drive
StringReplace, File_Name, File_Name,`n, \
Loop, parse, name, `n
{if a_index = 2
msgbox, %A_LoopField%
Run % "C:\Program Files\VideoLAN\VLC\vlc.exe -I dummy -v """ File_Name """ :sout=#transcode{vcodec=none,acodec=mp3,ab=128,channels=2,samplerate=44100}:standard{access=""file"",mux=dummy,dst=""" A_LoopField ".mp3""} "
}
I was wondering if it's possible to use findstr and/or gawk to return the output of a windows cmd exactly how I need it to be. I'm currently returning the output raw, then stripping out the blank lines, and parsing out what I need. Just as a learning thing, I was hoping I could see how this can be done better.
The raw output:
Change 2086888 on 2012/01/23 by user1#server1
test_description_1.2.3.4#29816
Change 2086888 on 2012/01/23 by user1#server2
test_description2_4.5.6.7#29816
Change 2078677 on 2012/01/20 by user2#server1
test_description3_7.8.9.10#29816
I take that output and parse it out to this with php:
1. 2086888,test_description_1.2.3.4#29816
2. 2086888,test_description2_4.5.6.7#29816
3. 2078677,test_description3_7.8.9.10#29816
To make it a little easier on myself, I remove the blank lines from the output by piping it to findstr and using /V "^$". So it's | findstr /V "^$".
How can I get the output that I parse out with php directly from the command line?
for command in cmd.exe skips blank lines, so it may be easier to parse it this way:
#Echo Off
setlocal enabledelayedexpansion
set linenum=1
for /f "tokens=1,2" %%A in (output.txt) do #(
if %%A==Change set result=%%B
if not %%A==Change (
echo !linenum!. !result!,%%A
set /a linenum=!linenum!+1
)
)
endlocal