Error in batch file "..unexpected at this time batch file" - if-statement

I have a code in a batch file which is giving an error:
56 was unexpected at this time
at if condition (if %fileSize% == 9363)
My code is:
for %%F in ("site_data.csv")
do set "fileSize=%%~zF"
if %fileSize% == 9363
(
pause
set sum2=%TIME:~3,2%
echo sum2=%sum2%
pause
if /f %sum2% gtr %sum1%
(
goto :p3
)
goto :p2
)
I don't understand what is the problem?

The "/F" parameter doesn't exist, please see the command help:
IF /?
And SUM1 variable doesn't exist in the example code that you given, so that can be another problem.
Try this:
#Echo OFF
for %%F in ("site_data.csv") do (set "fileSize=%%~zF")
IF %fileSize% EQU 9363 (set /A sum2=%TIME:~3,2%)
if %sum2% gtr %sum1% (goto :p3) ELSE (goto :p2)

Related

IF Input filename exists in Output folder, skip BUT ALSO SKIP in FOR Statement

Here is an excerpt of a long ffmpeg script I have and I have it:
Creating a text file of the video files in the current directory
With a FOR statement searching through the text file
Outputting to a subdir
What I want to add in is to not only not "process" go through the rest of the script if the file already exists but also not to process that ALREADY existing file. (In other words: If a copy of the file already exists in an output directory skip processing the file, but also to skip processing the duplicate file itself that was identified.)
dir *.mkv *.mp4 /A-D-H /B /S |findstr /R %Exclude-Final% /v /i>%TempFilePath%
Echo: These are the folders being Excluded: "!Exclude-AlltheseFolders!"
SET "FINALCOMMAND="
::******** DON'T EDIT-----Keeping Original Audio**************END END***************
SETlocal EnableExtensions DisableDelayedExpansion
SET "FilesFound=0" & SET "FilesEncoded=0" & SET "output="
for /F "delims=" %%I in (%TempFilePath%) do (
::ECHO ==!TIME!================Next File: %%I ========================
SET "output=%drive%%%~pI%%~nxI" & SET "filename=%%~nxI" & SET /A FilesFound+=1
SETlocal EnableExtensions EnableDelayedExpansion
IF exist "%drive%%%~pIoutput\%%~nxI" (SET "Convert_Audio1=N") ELSE IF !output2! == 1 (SET "Convert_Audio1=N") ELSE SET "Convert_Audio1=Y"
rem ===============================
rem FFProbe.exe evaluation of %%I files
rem ===============================
rem below still under the FOR statement above: for /F "delims=" %%I in (%TempFilePath%) do (
rem ------------------------------------------------------------
rem -----------------------------
IF !ConvertCodecs! == 1 (
SET /A count=5
IF /I "!output!" == "%%I" (
SET "output=%~dp0output\!filename!"
rem ECHO This is OUTPUT-DIR "%~dp0output\"
MKDIR "%~dp0output\"
) ELSE (
MKDIR "%drive%%%~pI"
)
ENDLOCAL
......
ENDLOCAL
ENDLOCAL
ENDLOCAL
```
I want filtration to all occur here, before it goes through the FFProbe.exe processing to speed it up. I assume in the 1st IF statement there is something I can do, but when there are multiple files, or even just 2 + 1 sub-folder, it can not carry-over the right variable i.e.
this will skip file1, process file 2, and then try to process file3
EDIT: Here is the Full Code. You will need to input what you want the destination drive to be (i.e. C: or D: etc...). It will look for mkv's and mp4's that have eac3,flac,dts,pcm,aac,or ac3 to convert to aac. ( Batch Convert Videos audio from one format to another )
#ECHO OFF
SETlocal
SET drive="~dp0"
SET string=%CD%
SETlocal EnableExtensions EnableDelayedExpansion
SET "drive=G:"
SET ^"Exclude-AlltheseFolders=#snapshot^"
SET "Convert_Audio1=Y"
SET "Convert_TO=aac"
SET "Codec1=eac3"
SET "Codec2=flac"
SET "Codec3=dts" &SET "Codec4=pcm_s24le" &SET "Codec5=aac" &SET "Codec6=ac3"
SET "KeepExtraAudio_NoOrig=Y"
SET "KeepOrigAudio=N"
SET "OverWriteFiles=N"
SET "ExtractTime=Y"
SET "time_to_start_from=00:00:10" &SET "duration_to_capture=00:00:15"
SET "TempFilePath=C:\Windows\Temp\ffmpeg-CountingScript-AllFilesInCurrentDirlist%DT%--%HH%.%MM%.%SS%.txt"
IF !ExtractTime! == Y ( SET "FFmpgextractTime= -ss !time_to_start_from! -t !duration_to_capture!")
ECHO THIS IS JMK1
IF !OverWriteFiles! == Y (SET "OverWrite=-y ") ELSE (SET "OverWrite=-n ")
IF !Convert_Audio1! == Y (
IF !Convert_TO! == aac ( set "Convert_TO=libfdk_aac" )
SET "FFmpgConvertStream1=-c:a:0 !Convert_TO! -b:a:0 640k -disposition:a:0 default"
IF !KeepExtraAudio_NoOrig! == Y (
SET "FFmpgXtraStream=-c:a copy"
)
IF !KeepOrigAudio! == Y (
SET "KeepOrigAudio_ffMpg=-map 0:a:0? -c:a:0 copy"
SET "KeepExtraAudio_NoOrig=Y"
)
) ELSE (
SET "ConvertCodecs=1"
SET "KeepOrigAudio_ffMpg=-c:a:0 copy"
SET "KeepExtraAudio_NoOrig=Y"
)
SET "delm1=^\^>" /c:"^\^<"
SET ^"Exclude-Final=/c:"\^<!Exclude-AlltheseFolders!\^>"^"
SET ^"Exclude-Final=!Exclude-Final:,=%delm1%!^"
dir *.mkv *.mp4 /A-D-H /B /S |findstr /R %Exclude-Final% /v /i>%TempFilePath%
Echo: These are the folders being Excluded: "!Exclude-AlltheseFolders!"
SET "FINALCOMMAND="
SETlocal EnableExtensions DisableDelayedExpansion
SET "ProgramFolder=C:\Program Files\FFmpeg-v2020\bin"
SET "ProbeOptions=-v quiet -select_streams a:0 -show_entries "stream^^=codec_name" -of json"
SET "FilesFound=0" & SET "FilesEncoded=0" & SET "output="
for /F "delims=" %%I in (%TempFilePath%) do (
SET "output=%drive%%%~pI%%~nxI" & SET folder=%drive%%%~pI & SET "filename=%%~nxI" & SET /A FilesFound+=1
SETlocal EnableExtensions EnableDelayedExpansion
IF exist "%drive%%%~pIoutput\%%~nxI" (SET "Convert_Audio1=N") ELSE IF !output2! == 1 (SET "Convert_Audio1=N") ELSE SET "Convert_Audio1=Y"
IF "!Convert_Audio1!" == "Y" (
SET "AudioCodec=" & SET "ConvertCodecs="
for /F "eol={ tokens=1,2 delims=,:[ ]{} " %%B in ('""%ProgramFolder%\ffprobe.exe" %ProbeOptions% "%%I""') do (
IF "%%~B" == "codec_name" (
IF not defined AudioCodec (
SET "AudioCodec=%%~C"
)
IF "%%~C" == "%Codec1%" (SET "ConvertCodecs=1"
) else IF "%%~C" == "%Codec2%" (SET "ConvertCodecs=1" & ECHO Codec is: %%~C
) else IF "%%~C" == "%Codec3%" (SET "ConvertCodecs=1" & ECHO Codec is: %%~C
) else IF "%%~C" == "%Codec4%" (SET "ConvertCodecs=1" & ECHO Codec is: %%~C
) else IF "%%~C" == "%Codec5%" (SET "ConvertCodecs=1" & ECHO Codec is: %%~C
) else IF "%%~C" == "%Codec6%" (SET "ConvertCodecs=1" & ECHO Codec is: %%~C
)
)
)
)
IF !ConvertCodecs! == 1 (
ECHO [91m==!TIME!================[0m!Codec1! [94min[0m- %%I [91m=========[0m
)
IF "%~dp0output\!filename!" == "%%I" (set "ConvertCodecs=0")
IF !ConvertCodecs! == 1 (
SET /A count=5
IF /I "!output!" == "%%I" (
SET "output=%~dp0output\!filename!"
SET /A count+=1
MKDIR "%~dp0output\"
) ELSE (
MKDIR "%drive%%%~pI"
)
SET "FINALCOMMAND=ffmpeg !OverWrite!-hide_banner%FFmpgextractTime% -loglevel quiet -hwaccel auto -stats -i "%%I" -map 0:v -map_metadata 0 -movflags use_metadata_tags -map 0:a? -map 0:s:0? -c:s:0 copy -c:v copy %FFmpgXtraStream% %FFmpgConvertStream1% %KeepOrigAudio_ffMpg% "!output!" "
ECHO this is the command1: !FINALCOMMAND!
!FINALCOMMAND!
ECHO [91m=====[0mCOMPLETE[91m===============[0m .
IF not %FilesEncoded% == 0 ECHO This one was a failure. Count Encoded so far: "%FilesEncoded%"
IF not errorlevel 1 SET /A FilesEncoded+=1
powershell "$target = gi '!output!'; $source = gi '%%I'; 'CreationTime', 'LastWriteTime', 'LastAccessTime' | foreach { $target.$_ = $source.$_ }"
for /F "delims=" %%p in ("!ConvertCodecs!") do (
ECHO THIS IS P: %%p
ENDLOCAL
SET /A FilesEncoded=%%p+FilesEncoded
)
) ELSE ( ECHO ##NOT PROCESSING##: !TIME! - %%I ## & ECHO [91m=====--[0mFILE ALREADY EXISTS! [91m======================[0m Next File [91m===========================[0m )
)
)
IF %FilesFound% == 1 ( SET "PluralS=" ) else SET "PluralS=s"
ECHO [91m***************************************************************************************[0m
ECHO Re-encoded %FilesEncoded% of %FilesFound% video file%PluralS%.
ECHO [91m***************************************************************************************[0m
endlocal
endlocal
endlocal
exit /b
I think I found the answer (which I already had built-in).
In the the settings sections I designed, on the top of the full code, Under the 2nd SetLocal, SET ^"Exclude-AlltheseFolders=#snapshot^" variable, I adjusted to SET ^"Exclude-AlltheseFolders=#snapshot,output^"
This is then used to set the Exclude-Final variable:
SET ^"Exclude-Final=/c:"\^<!Exclude-AlltheseFolders!\^>"^"
SET ^"Exclude-Final=!Exclude-Final:,=%delm1%!^"
Which is then used here:
dir *.mkv *.mp4 /A-D-H /B /S |findstr /R %Exclude-Final% /v /i>%TempFilePath%
Echo: These are the folders being Excluded: "!Exclude-AlltheseFolders!"
So now as a summary I have it now excluding any folder/files "output*filename*" which I have setup as a possible output if files exist in the folder being processed from, which is next farther down the code, where it checks if file exists in current directory then create output*filename* instead.
IF !ConvertCodecs! == 1 (
SET /A count=5
IF /I "!output!" == "%%I" (
SET "output=%~dp0output\!filename!"
SET /A count+=1
MKDIR "%~dp0output\"
) ELSE (
MKDIR "%drive%%%~pI"
)
Excerpt of full settings code with Comments:
SETlocal EnableExtensions EnableDelayedExpansion
:: #echo on
::#######0-OVERRIDE Root Directory but keep LOGGING the SAME #############
SET "drive=G:"
::#######1-Exclude Specific Sub-Directories? #############
SET ^"Exclude-AlltheseFolders=#snapshot,output^"
:: #rem SET ^"Exclude-AlltheseFolders=#snapshot,Archive,Archive02.01,Archive2021.01.22,Video,Video2,aVideo,^!.Blu-Ray^ Final^"
::#######2-Convert Audio Track? #############
SET "Convert_Audio1=Y"
rem Rev V2.6.8.5 ADD Convert 1st group to AC3 (channel5.1 + above?), then convert 2nd group to aac (2-channel for commentary??)
SET "Convert_TO=aac"
:: rem ac3 or aac
::#######3-Codecs Desired to Convert #############
SET "Codec1=eac3"
SET "Codec2=flac"
SET "Codec3=dts" &SET "Codec4=pcm_s24le" &SET "Codec5=aac" &SET "Codec6=ac3"
:: rem pcm_s24le , null , vorbis
::#######4-Keep orig Audio Track? #############
SET "KeepExtraAudio_NoOrig=Y"
SET "KeepOrigAudio=N"
SET "OverWriteFiles=N"
::#######4-Keep orig Audio Track? #############
:: MODIFY
:: Extract Time AND what to Extract (as a sample test)
SET "ExtractTime=Y"
SET "time_to_start_from=00:00:10" &SET "duration_to_capture=00:00:15"
rem SET "time_to_start_from=00:00:10" &SET "duration_to_capture=03:00:00"
::
::
::
::#######END OF SETTINGS###############################################
::*********************************************************************
SET "TempFilePath=C:\Windows\Temp\ffmpeg-CountingScript-AllFilesInCurrentDirlist%DT%--%HH%.%MM%.%SS%.txt"
::#######END OF SETTINGS################################################################################################################################################################################################################
::**************************************************************************************************************************************************************************************************************************************
::#######END OF SETTINGS################################################################################################################################################################################################################
::******** DON'T EDIT-----Keeping Original Audio ***************************************************************************************************************************************************************************************
IF !ExtractTime! == Y ( SET "FFmpgextractTime= -ss !time_to_start_from! -t !duration_to_capture!")
ECHO THIS IS JMK1
IF !OverWriteFiles! == Y (SET "OverWrite=-y ") ELSE (SET "OverWrite=-n ")
IF !Convert_Audio1! == Y (
IF !Convert_TO! == aac ( set "Convert_TO=libfdk_aac" )
SET "FFmpgConvertStream1=-c:a:0 !Convert_TO! -b:a:0 640k -disposition:a:0 default"
IF !KeepExtraAudio_NoOrig! == Y (
SET "FFmpgXtraStream=-c:a copy"
)
IF !KeepOrigAudio! == Y (
SET "KeepOrigAudio_ffMpg=-map 0:a:0? -c:a:0 copy"
SET "KeepExtraAudio_NoOrig=Y"
)
) ELSE (
SET "ConvertCodecs=1"
SET "KeepOrigAudio_ffMpg=-c:a:0 copy"
SET "KeepExtraAudio_NoOrig=Y"
)
SET "delm1=^\^>" /c:"^\^<"
SET ^"Exclude-Final=/c:"\^<!Exclude-AlltheseFolders!\^>"^"
SET ^"Exclude-Final=!Exclude-Final:,=%delm1%!^"
:: ECHO This is the date and time: %DT%--%HH%.%SS%
dir *.mkv *.mp4 /A-D-H /B /S |findstr /R %Exclude-Final% /v /i>%TempFilePath%
Echo: These are the folders being Excluded: "!Exclude-AlltheseFolders!"

Batch file keeps crashing at if statement

I am making a simple text game. Everything works fine until it gets to the if statement. I do not know what i am doing wrong.
#echo off
title Text Adventures
echo "What is your name?"
set /p name=
echo "That was a bad crash. Are you hurt, %name%?"
echo.
echo Y/N
set /p answer=
if %answer% equ y goto hurt
:hurt
echo.
echo "I see. That's a gnarly gash you've got there!"
Here I have re-written this to be in a form that uses Functions and uses the suggestions I provided to the original post as comments.
You know I assumed incorrectly that you had a purpose to using the labels, but given the way the question has give I think you would do well to not bother with them.
Here is a no-labels version:
#(SETLOCAL
echo off
title Text Adventures
)
CALL :Main
( ENDLOCAL
ECHO. The Script Ended!
PAUSE
EXIT /B
)
:Main
set /p "name=What is Your Name?"
ECHO.
CHOICE /M "That was a bad crash. Are you hurt, %name%?"
If %ERRORLEVEL% equ 1 (
echo.
echo "I see. That's a gnarly gash you've got there!"
) ELSE (
echo.
echo "Oh Good!"
)
PAUSE
GOTO :EOF
Here is the labels version. (I removed the comments explaining how it works and why the code is there so it isn't so cluttered for you.)
#(SETLOCAL
echo off
title Text Adventures
)
CALL :Main
( ENDLOCAL
ECHO. The Script Ended!
PAUSE
EXIT /B
)
:Main
set /p "name=What is Your Name?"
ECHO.
CHOICE /M "That was a bad crash. Are you hurt, %name%?"
If %ERRORLEVEL% equ 1 (
CALL :Hurt
) ELSE (
CALL :NotHurt
)
PAUSE
GOTO :EOF
:Hurt
echo.
echo "I see. That's a gnarly gash you've got there!"
GOTO :EOF
:NotHurt
echo.
echo "Oh Good!"
GOTO :EOF
For this sort of thing I prefer by far using choice, and frequently use my menu macro that returns the selected option as a string in the variable option
below is a shell script that demonstrates the usage of a few macro's I frequently use.
#ECHO Off & Goto :main
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::: * Functions * :::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:+------------------------------------------------------------------------------------------------+:
:ColorString
(For %%C in (%~1)Do Set "rv=!rV!%/E%!#A!m%%~C%/E%0m"& Set /A "#A+=1"& IF "!#A!"=="37" (Set #A=31))
Exit /B 0
:+------------------------------------------------------------------------------------------------+:
:ColorMenu
rem Set /A "RR=!random! %%195 + 60","GG=!random! %%195 + 60","BB=!random! %%195 + 60"
rem Set "%~1=%/E%38;2;!RR!;!GG!;!BB!m!%~1!%/E%0m"
Set "rV="& IF "!#A!"=="" (Set #A=32)
(For %%C in ("!%~1!")Do Set "rv=!rV!%/E%!#A!m%%~C%/E%0m"& Set /A "#A+=1"& IF "!#A!"=="37" (Set #A=31)) & Set "%~1=!rV!"
Exit /B 0
:+------------------------------------------------------------------------------------------------+:
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:main * Environment Definition * :::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Rem /* ensure correct environment for macro definitions */
Endlocal & Setlocal DISABLEdelayedexpansion
:+------------------------------------------------------------------------------------------------+:
For /F %%a in ('echo prompt $E ^| cmd')do (Set "/E=%%a[")
:+------------------------------------------------------------------------------------------------+:
Set "ChoList=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Set "ColLETTERS=Set "Rv="& Set "#A=31" & (For %%A in ("$Str")Do Set "Word=%%~A" & For %%B In (0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z . + - _ [ ] / \ ":")Do Set "Word=!Word:%%~B=%%~B !") & (Call :ColorString "!Word!" & Echo/!rV!)"
Set "ColWORD/S=Set "#A=35"& Set "MSG=$Str" & For %%G in ("!MSG!")Do (For %%v in (%%~G)Do (Set "Rv="&Call :Colorstring "%%~v"& For %%x in (!Rv!)Do (Set "MSG=!MSG:%%~v=%/E%0m%%~x!")))&Echo/!MSG!"
Set "List/D/V=Set "#$L=0"&Set "$$L="&For %%n in (1 2)Do if %%n==2 (For %%G in (!$L!)Do (Set "%%~G" > Nul &Set /A "#$L+=1"))Else Set $L="
Set "Menu=For %%n in (1 2)Do if %%n==2 (!DIV!&Set "CH#=0"&(Set "CHCS="&For %%G in (!Options!)Do For %%i in (!CH#!)Do (Set "CHCS=!CHCS!!ChoList:~%%i,1!"&Set "Opt[!ChoList:~%%i,1!]=%%~G"& Set "Opt=%%~G" &Call :ColorMenu Opt &<Nul Set /P "=[!ChoList:~%%i,1!] !Opt!"&Set /A "CH#+=1"&Echo/))&!DIV!& For /F "Delims=" %%o in ('Choice /N /C:!CHCS!')Do (Set "OPTION=!Opt[%%o]!"))Else Set Options="
Set "ColLINE=For %%n in (1 2)Do if %%n==2 (Echo/!$C!!$Str!%/E%0m)Else Set $Str="
:+------------------------------------------------------------------------------------------------+:
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::: * Script Body * :::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Setlocal EnableDelayedExpansion
for /F "usebackq tokens=2* delims=: " %%W in (`mode con ^| findstr Columns`) do Set "Console_Width=%%%W"
Set "DIV="&For /L %%i in (2 1 %Console_Width%)Do Set "DIV=!DIV!-"
Set "DIV=Echo/%/E%33m!DIV!%/E%0m"
%List/D/V:$L=Colors%"Red=%/E%31m" "Yellow=%/E%33m" "Green=%/E%32m" "Blue=%/E%34m" "Purple=%/E%35m" "Cyan=%/E%36m" "White=%/E%37m" "Gray=%/E%90m" "Pink=%/E%91m" "Beige=%/E%93m" "Aqua=%/E%94m" "Magenta=%/E%95m" "Teal=%/E%96m" "Off=%/E%0m" "Black=%/E%30m"
%List/D/V:$L=Actions%"Buy a house=Did you win the lotto" "Go for a drive=Start your engines" "Walk on the wild side=Get mauled by a lion" "Run a mile=Fit yet" "flee the realm=fall down a hole" "battle trolls=A losing battle" "puzzle a conundrum=Enigma's Stigmatised" "solve 42=life is meaningless"
%ColLETTERS:$Str=Welcome.%
%ColWORD/S:$Str=Hello there my friend^! How are you today.%
%ColLINE:$C=Teal%What a world we live in^^!
%Menu%"Buy a house" "Go for a drive" "Walk on the wild side" "Run a mile" "flee the realm" "battle trolls" "puzzle a conundrum" "solve 42"
For %%G in ("!Option!")Do Echo/!%%~G!
The menu macro builds a list of choices for each argument it's supplied, using substring modification to iterate over a 36 character choice list to build the final choice options - meaning support for 36 menu options.
Update
An additional example has been added to show a way to use the selection to display output or take actions without requiring conditional testing. Using the List/D/V macro to define values to options, a selected OPTION can be expanded directly. In the example, it's just to display output, however values can be assigned containing simple commands like Set, Goto or call to perform specific actions for the chosen menu option.
I forgot to add pause
#echo off
title Text Adventures
echo "What is your name?"
set /p name=
echo "That was a bad crash. Are you hurt, %name%?"
echo.
echo Y/N
set /p answer=
if %answer% equ y goto hurt
:hurt
echo.
echo "I see. That's a gnarly gash you've got there!"
pause

Extract a number from string in batch script

I've been struggling to write a script that will find the drive index number from other properties of the drive. The script is as follows:
#echo off
REM batch file to load Veracrypt
Set "driveIndex="
for /f "skip=1 tokens=1 delims= " %%a in ('wmic diskdrive where "model ='WD Elements 1078 USB Device'" get index') do SET driveIndex=%%a & goto reportLetter
:reportLetter
if not defined driveIndex (
echo Error Occured!
pause
exit
) else (
echo \Device\Harddisk%driveIndex:~0%\Partition3
pause
exit
)
However, the output of the script is \Device\Harddisk1 \Partition3. I tried for a long long time but could get the script to give the following output: \Device\Harddisk1\Partition3.
Could anyone tell me how to correct the code to get the required output?
Try this
DO SET "driveIndex=%%a"
Your line
... do set driveIndex=%%a & goto ...
is interpreted as set driveIndex=%%a<space>& goto ..., this is, where the additional space in \Device\Harddisk1 \Partition3 comes from.
Of course you could write:
... do set driveIndex=%%a& goto ...
but the better syntax is:
... do set "driveIndex=%%a" & goto ...
which eliminates any unintended spaces.
Note1: set is very picky with spaces. set var = hello creates a variable named var<space> with the value <space>hello<space>.
Note2:
set var="value" sets the value to "value"
set "var=value"sets the value to value. This syntax gives you full (and visible) control to the variable name and it's value.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET DRIVE_INDEX=
FOR /F "usebackq skip=1" %%i IN (`wmic diskdrive where "model = 'HGST HTS725050A7E630 ATA Device'" get index`) DO (
IF "!DRIVE_INDEX!" EQU "" (SET DRIVE_INDEX=%%i)
)
ECHO DRIVE_INDEX is set to %DRIVE_INDEX%
I believe that the problem is that WMIC output is Unicode.
I'd try
for /f "skip=1 tokens=1 delims= " %%a in ('wmic diskdrive where "model ='WD Elements 1078 USB Device'" get index^|more') do SET driveIndex=%%a & goto reportLetter
where the ^|more converts to ANSI. The caret escapes the pipe to tell cmd that the pipe is part of the command to be executed.

monitoring a log file for a specific pattern

I am trying to write a batch file to monitor a log file for the word 'rdy' on a line and alert if the value against rdy is less than 200
extract from my log file as below:
[Sun Jun 23 11:00:00 2013] [notice] mpmstats: rdy 249 bsy 1 rd 0 wr 1 ka 0 log 0 dns 0 cls 0
[Sun Jun 23 11:00:02 2013] [error] [client 10.25.134.1] File does not exist: E:/htdocs/default/KeepAlive.html
I have written a basic script ( Still on my L's ) which monitors the error.log file in a particular directory. The issue is there are error logs from multiple days and I want to monitor the current error log.
#echo off
set log=E:\scripts\busycheckalert.log
set Time=%time:~0,5%
set Today=%date:~4,2%
set Month=%date:~7,2%
set Year=%date:~12,2%
set file=E:\logs\ihs\Default\error.log.%Month%.%Today%.%Year%
echo Polling %file% at %Time% >> %log%
for /f "usebackq delims=;" %%a in (`dir /b E:\logs\ihs\Default\error.log.%Month%.%Today%.%Year%`) do (
echo Checking now >> %log%
for /f "tokens=8,9 delims= " %%a in (E:\logs\ihs\Default\error.log.%Month%.%Today%.%Year%) do (
echo Doing Checks >> %log%
if %%j LEQ 200 echo %Today%-%Month%-%Year% at %Time% Error - Ready threshold exceeded >> %log% in %%a ))
I manage to get till the first checkpoint " Checking now". However, it seems it doe not enter that 2nd loop.
This is the extract from the resultant log file:
Polling E:\logs\ihs\Default\error.log.06.23.13 at 22:48
Checking now
Polling E:\logs\ihs\Default\error.log.06.23.13 at 22:49
Checking now
Polling E:\logs\ihs\Default\error.log.06.23.13 at 22:50
Checking now
Could you please advise where I am going wrong? Any help would be great.
Thanks
for /f "tokens=8,9 delims= " %%a in (E:\logs\ihs\Default error.log.%Month%.%Today%.%Year%) do (
Hmmm- now I wonder what would happen if you were to change the %%a to, say, %%i ?
You appear not to be checking that %%i==rdy either. If you don't do that, you may land up with some rather odd results.
The issue is there are error logs from multiple days and I want to monitor the current error log.
for /f "delims=" %%a in (' dir /b /a-d /od *.log ') do set "latest_file=%%a"
I gather now that it's not your aim.
You seem to be using the same log file name as the file you are processing.
You have delims=; where there are no ; in your log snippet.
You are reusing %%a in both loops.
set file=E:\logs\ihs\Default\error.log.%Month%.%Today%.%Year%
echo Polling %file% at %Time% >> %log%
for /f "usebackq delims=;" %%a in (`dir /b E:\logs\ihs\Default\error.log.%Month%.%Today%.%Year%`) do (
echo Checking now >> %log%
for /f "tokens=8,9 delims= " %%a in (E:\logs\ihs\Default\error.log.%Month%.%Today%.%Year%) do (
Suggestion with code for GNUWin32 grep:
#echo off & setlocal
set "cTime=%time:~0,5%"
set "Today=%date:~3,2%"
set "Month=%date:~6,2%"
set "Year=%date:~11,2%"
set "file=E:\logs\ihs\Default\error.log.%Month%.%Today%.%Year%"
SET "log=resultant.log"
echo Polling %file% at %Time% >> "%log%"
for /f "delims=" %%a in ('dir /b /a-d "%file%') do (
echo Checking now >> "%log%"
for /f "tokens=3" %%b IN ('grep -o "mpmstats: rdy [0-9]\+" "%file%"') do SET "rdy=%%b"
echo Doing Checks >> "%log%"
SETLOCAL ENABLEDELAYEDEXPANSION
if !rdy! LEQ 200 echo %Today%-%Month%-%Year% at %cTime% Error - Ready threshold exceeded IN %%a >> "%log%"
endlocal
)
You are using a specific file in your FOR loops, so there is no need for two of them. The first one merely confirms that the file exists. That is easier and more efficiently done with:
if exist "E:\logs\ihs\Default\error.log.%Month%.%Today%.%Year%" ( ... )
Others have said you have a problem using %%a for both loops. Actually, there is nothing wrong with reusing a character within nested loops. But then your inner loop cannot access the outer loop value. Given that your inner loop DO references %%j, I suspect you intended for your inner loop to use %%i instead of %%a.
Your logic is wrong in that your loop is processing all lines, when it should only process lines that contain " rdy ". FIND or FINDSTR can be used to efficiently filter out unwanted lines.
You should never assign your own value to a variable named TIME (note that variable names are case insensitive). Doing so prevents you from later accessing the dynamic time value.
I haven't figured out what would prevent entry to your inner loop when the outer loop works. But I would restructure your entire code.
Instead of deriving the name of the log file from the current date, I would list all log files in date/time order and use FOR /F to capture the last one found.
Then I would use another FOR /F to parse the output of a FINDSTR search for " rdy "
#echo off
setlocal
set "log=E:\scripts\busycheckalert.log"
set "checkTime=%time:~0,5%"
pushd "E:\logs\ihs\Default"
set "currentLog="
for /f "delims=" %%F in ('dir /b /a-d /od "error.log.*"') do set "currentLog=%%F"
if defined currentLog (
>>"%log%" echo Polling %currentLog% at %checkTime%
for /f "tokens=9" %%A in ('findstr /c:" rdy " "%currentLog%"') do (
if %%A leq 200 >>"%log%" echo Error at %time%: Ready threshold exceeded in %currentLog%
)
) else >>"%log%" echo No log found at %checkTime%"
popd

Is there a unit-test framework for Windows batch files?

I need just something very simple like "run this command and succeed if there is 'this string' somewhere in the console output, fail otherwise". Is there such a tool?
Not that I'm aware of, but you can easily write one in another batch script.
call TestBatchScript.cmd > console_output.txt
findstr /C:"this string" console_output.txt
will set %errorlevel% to zero if the string is found, and nonzero if the string is absent. You can then test that with IF ERRORLEVEL 1 goto :fail and execute whatever code you want after the :fail label.
If you want compact evaluation of several such strings, you can use the || syntax:
call TestBatchScript.cmd > console_output.txt
findstr /C:"teststring1" console_output.txt || goto :fail
findstr /C:"teststring2" console_output.txt || goto :fail
findstr /C:"teststring3" console_output.txt || goto :fail
findstr /C:"teststring4" console_output.txt || goto :fail
goto :eof
:fail
echo You Suck!
goto :eof
Or, you can go even further and read the list of strings from a file
call TestBatchScript.cmd > console_output.txt
set success=1
for /f "tokens=*" %%a in (teststrings.txt) do findstr /C:"%%a" console_output.txt || call :fail %%a
if %success% NEQ 1 echo You Suck!
goto :eof
:fail
echo Didn't find string "%*"
set success=0
goto :eof
I use the following for filter type commands:
For batch file foo.cmd, create the following files:
foo.in.txt:
hello
foo.expected.txt:
hello world
foo.test.cmd:
#echo off
echo Testing foo.cmd ^< foo.in.txt ^> foo.out.txt
call foo.cmd < foo.in.txt > foo.out.txt || exit /b 1
:: fc compares the output and the expected output files:
call fc foo.out.txt foo.expected.txt || exit /b 1
exit /b 0
Then run foo.test.cmd
The below mentioned repo has been deleted and is unfortunately no longer available.
I have created a library for windows batch unit testing. It is currently in its infancy, but it works and I use it.
It is called cmdUnit and it can be downloaded from the project site on bitbucket:
https://bitbucket.org/percipio/cmdunit