I'm trying to compare a sequence of 9 numbers (separated by ,) using a batch file.
The comparison is always made by the corresponding sequence like:
mPrevious[0] <-> mCurrent[0]
mPrevious[1] <-> mCurrent[1]
I need to know if at least one sequece have changed. In the example bellow, 234 changed to 230 and 146 to 149.
The sketch I have so far is:
setlocal ENABLEDELAYEDEXPANSION
#echo off
set mPrevious=229,234,235,127,58,0,131,133,146
set mCurrent=229,230,235,127,58,0,131,133,149
for /f "tokens=1,2,3,4,5,6,7,8,9 delims=," %%a IN ('echo !mPrevious!') do (
)
The number of entries (currently 9) might change in the future. But for now they are just 9.
I'm not sure what is the proper way to do it inside a batch script.
#echo off
title <nul && title ...\%~nx0
setlocal enabledelayedexpansion
set "_mPrevious=229,234,235,127,58,0,131,133,146"
set "_mCurrents=229,230,235,127,58,0,131,133,149"
echo/!_mPrevious!|find "!_mCurrents!" >nul && (
endlocal & echo\Nothing changed^!! & goto :EOF )
for %%i in (!_mPrevious!)do set /a "_i+=1+0" && call set "_mPrev_!_i!=%%~i"
for %%j in (!_mCurrents!)do set /a "_j+=1+0" && call set "_mCurr_!_j!=%%~j"
if !_i! neq !_j! endlocal & echo\Varyables have different lengths^!! & goto :EOF
for /L %%L in (1 1 !_j!)do if !_mPrev_%%~L! neq !_mCurr_%%~L! echo\!_mPrev_%%~L! updated to: !_mCurr_%%~L!
endlocal && goto :EOF
Outputs:
234 updated to: 230
146 updated to: 149
One simple way to do this only if necessary and only if both variable has same length:
Make a first comparison if the variables are the same, there was a change in the values:
echo/!_mPrevious!|find "!_mCurrents!" >nul && (
endlocal & echo\Nothing changed^!! & goto :EOF )
And a second if they continue with the same length:
if !_i! neq !_j! endlocal & echo\Variables have different lengths^!! & goto :EOF
Obs.: 1. I prefer replace [ ] to one simple _
Obs.: 2. Also, change i+= to _i+=1+0, where no need predefined set command: set i=0
The FOR token delimiters are: <SPACE> <TAB> <NBSP> , ; =
Therefore, you can put it into a FOR loop, but it would fail if the content contained * or ?.
#echo off
====SETLOCAL EnableDelayedExpansion EnableExtensions
set/a"#=cnt=0"
::Define lists
set "mPrevious=229,234,235,127,58,0,131,133,146"
set "mCurrent=229,230,235,127,58,0,131,133,149"
FOR %%P in (!mPrevious!) do (
FOR %%C in (!mCurrent!) do (
if !cnt! equ !#! echo(%%P %%C
set/a"cnt+=1"
)
set/a"cnt=0,#+=1"
)
This is an approach using some self-expanding code:
#echo off
setlocal EnableDelayedExpansion
rem // Define constants here:
set "mPrevious=229,234,235,127,58,0,131,133,146"
set "mCurrents=229,230,235,127,58,0,131,133,149"
rem // Initialise auxiliary variables and indexes:
set "nPrevious=,%mPrevious%" & set /A "i=0"
set "nCurrents=,%mCurrents%" & set /A "j=0"
rem // Convert lists to arrays using self-expanding code:
set "_=%nPrevious:,=" & set /A "i+=1" & set "nPrevious[!i!]=%"
set "_=%nCurrents:,=" & set /A "j+=1" & set "nCurrents[!j!]=%"
rem // Verify availability of arrays:
> nul 2>&1 set nPrevious[ || set /A "i=0"
> nul 2>&1 set nCurrents[ || set /A "j=0"
rem // Determine minimal and maximal count:
if %j% gtr %i% (set /A "k=i, l=j" & set "_=#") else (set /A "k=j, l=i" & set "_=")
rem // Compare corresponding elements:
for /L %%K in (1,1,%k%) do if !nPrevious[%%K]! neq !nCurrents[%%K]! (
echo [%%K]: !nPrevious[%%K]! -^> !nCurrents[%%K]!
)
rem // Return removed or added elements:
set /A "k+=1" & for /L %%K in (!k!,1,%l%) do if defined _ (
echo [%%K]: --- -^> !nCurrents[%%K]!
) else (
echo [%%K]: !nPrevious[%%K]! -^> ---
)
endlocal
Sample output, relying on the data of the question:
[2]: 234 -> 230
[9]: 146 -> 149
I have a batch script which :
check the files in a directory and check if it exists in another
directory and it should not exists there
count each file with a specific format, there should be just one of each
if both of the above statement is true then generate a success file.
Below is my code which is working fine:
SET /A file1=file2=Val=0
SET /A FileE=1
set /a flagname=1
for %%A in (*ABC*.txt) do set /a file1+=1
for %%A in (*XYZ*.txt) do set /a file2+=1
for %%i in ("*") do if exist "Processed\%%~nxi" SET /A FileE=0
SET /A Val=%file1%*%file2%*%FileE%
if %Val% EQU 1 (
echo SUCESS>Sucess.txt
SET Flag=Sucess
echo %Flag%) else (
if %file1% EQU 0 ( echo Missing ABC.txt files >> Error.txt)
if %file1% GTR 1 ( echo More than 1 ABC.txt files >> Error.txt)
if %file2% EQU 0 ( echo Missing XYZ.txt files >> Error.txt)
if %file2% GTR 1 ( echo More than 1 XYZ.txt files >> Error.txt)
(for %%i in ("*") do if exist "Processed\%%~nxi" echo(File Exists in
Processed
Folder %%~i)>>Error.txt
SET Flag=FAILURE
echo %Flag%)
My problem is how to transform above code to iterate over a list of number of files like 100 ? Below is the code which I tried :
#echo off
setlocal enable delayed expansion
Set Filen[0]=ABC*.txt
Set Filen[1]=XYZ*.txt
SET /A Val=1
SET /A File1=0
FOR /l %%G in (0,1,1) Do (
echo !Filen[%%G]! hi
set File1=0
echo %file1% Count
for %%A in (!Filen[%%G]! ) do (
set File1=!File1!+1
echo %%A %file1%)
)
Put your search words in a string and iterate over it:
Set "Search=ABC DEF XYZ"
For %%A in (%Search%) do (
Or in a file and read one by one
For /f "usebackq" %%A in ("Search.txt") Do (
With this file Search.txt
ABC
DEF
XYZ
In the environment
> tree a:\ /F
Auflistung der Ordnerpfade für Volume RamDisk
A:\
└───Test
│ ABC_123.txt
│ DEF_456.txt
│ Search.txt
│
└───Processed
The following batch
:: Q:\Test\2018\07\01\SO_51120147.cmd
#Echo off & Setlocal EnableDelayedExpansion
Set "BaseDir=A:\Test"
Set Err=^>^> "Error.txt" Call Echo=[%%date%% %%time%%]
PushD "%BaseDir%" || (%Err% can't locate %BaseDir% & Pause &Goto :Eof)
%Err% Job %~f0 started by %USERNAME%
Set " Flag=Sucess"
:: Uncomment for string variant
:: Set "Search=ABC DEF XYZ"
:: For %%A in (%Search%) do (
:: use the file variant
For /f "usebackq" %%A in ("Search.txt") Do (
Set Cnt=0
For %%B in (%%A*.txt) Do Set /A Cnt=1
if !Cnt! NEQ 1 (
%Err% Count of %%A*.txt file=[!Cnt!]
SET Flag=FAILURE
)
)
For %%A in (*) do if exist "Processed\%%~nxA" (
%Err% File %%A does exist in Processed Folder
Set Flag=FAILURE
)
%Err% Job %~f0 terminated with %Flag%
Yields this output:
> type A:\Test\Error.txt
[2018-07-01 13:10:34,43] Job Q:\Test\2018\07\01\SO_51120147.cmd started by LotPings
[2018-07-01 13:10:34,45] Count of XYZ*.txt file=[0]
[2018-07-01 13:10:34,47] Job Q:\Test\2018\07\01\SO_51120147.cmd terminated with FAILURE
EDIT: Explanation of the somehow tricky line:
Set Err=^>^> "Error.txt" Call Echo=[%%date%% %%time%%]
To not have to pre/append every line which should go to the error log with
the redirection and a (fixed) file name I put these together with the
echo command and a [date time] stamp into a variable.
To avoid immediate interpretation when setting the variable, the '>' have to
be esaped with a caret, and to delay the expansion of the %-signs these have
to be doubled. (otherwise each log entry had the same date time)
To force expansion of date time when echoing the (pseudo) call is neccessary.
I write script like this:
#ECHO OFF
setlocal EnableDelayedExpansion
set "remove=ABC"
echo. %remove%
Set FILENAME="456_789_ABC00011092_789_EFGHIK_56893.mpg"
for %%a in (%FILENAME:_=" "%) do (
set TEN=%%a
echo. %AB%
set "remove_1=ABC"
echo. %remove_1%
Set _TEN=!TEN:%remove%=!
echo. %_TEN%
Set i=0
IF !_TEN! NEQ !TEN! (
set /A i+=1
set "String[!i!]=%%~a"
)
)
pause
exit
Why echo. %AB% echo. %remove_1% result is
I replace % by !. It's work fine but command Set _TEN=!TEN:!remove_1!=! not run
Edit - (from the additional question currently posted as an answer)
When I use FindStr command like this:
for %%a in (%FILENAME:_=" "%) do (
echo %%a | findstr /I /R /C:"ABC" >nul
ECHO %errorlevel%
if "%errorlevel%" equ "0" (
set /A i+=1
set "String[!i!]=%%~a"
)
)
Why errorlevel always = 0
%AB% has not been defined within your posted script, so as it has no value will not be echoed, you will just get an empty line due to the . after echo. Because remove_1 is being set within the loop, (code block), you should be using the delayed expansion syntax, Echo !remove_1!. It is the same for echo. %_TEN%, i.e. Echo !_TEN!, and would have been Echo !AB! had it previously been defined. In order to get the double expansion needed to Set your _TEN variable, you could use a pseudo Call:
#Echo Off
SetLocal EnableDelayedExpansion
Set "FILENAME=456_789_ABC00011092_789_EFGHIK_56893.mpg"
For %%A In ("%FILENAME:_=" "%") Do (
Set "TEN=%%A"
Echo. !AB!
Set "remove_1=ABC"
Echo !remove_1!
Call Set "_TEN=!TEN:%%remove_1%%=!"
Echo !_TEN!
Set "i=0"
If "!_TEN!" NEq "!TEN!" (
Set /A i+=1
Set "String[!i!]=%%~A"
)
)
Pause
Exit /B
In your second related question, initially posted as an answer and now added as an edit to your original question; because the error level is being set within the loop, (code block), you should be using the delayed expansion syntax, !errorlevel!
#Echo Off
SetLocal EnableDelayedExpansion
Set "FILENAME=456_789_ABC00011092_789_EFGHIK_56893.mpg"
For %%A In ("%FILENAME:_=" "%") Do (
Echo %%A | FindStr /IRC:"ABC" >Nul
Echo !errorlevel!
If "!errorlevel!"=="0" (
Set /A i+=1
Set "String[!i!]=%%~A"
)
)
Set String[
Pause
Exit /B
Or if you don't need to Echo each error level to the screen, you can use a conditional statement &&:
#Echo Off
SetLocal EnableDelayedExpansion
Set "FILENAME=456_789_ABC00011092_789_EFGHIK_56893.mpg"
For %%A In ("%FILENAME:_=" "%") Do (
Echo %%A | FindStr /IRC:"ABC" >Nul && (
Set /A i+=1
Set "String[!i!]=%%~A"
)
)
Set String[
Pause
Exit /B
why doesn't this work?
SET FIRST=""
SET COUNT=0
FOR %%F IN (dir *.png) DO (
IF %COUNT% NEQ 0 GOTO _skip
SET FIRST=%%F
:_skip
ECHO "%%F",
SET /A COUNT=COUNT+1
)
It sets FIRST to the last *.png because the IF condition fails, because COUNT - although is incremented by set /A, the IF %COUNT% doesn't ever work. Very frustrating.
Don't need to count, just do goto skip after echo line.
#echo off
for /f "delims=" %%f in ('dir /b *.png') do (
rem :: you can use "echo %%f" instead of "set first=%%f"
set first=%%f
goto _skip
)
:_skip
echo %first%
you mixing two things to scan folder.
Here is the second way:
#echo off
for %%f in (*.png) do (
set first=%%f
goto _skip
)
:_skip
echo %first%
exit /b 0
If you need absolutely to count, here is the way to skip with count. As stated in comment, you need to enable delayedExpansion
#echo off
set count=1
for %%f in (*.png) do (
set first=%%f
setlocal enabledelayedexpansion
if "!count!"=="1" goto _skip
endlocal
set /a count+=1
)
:_skip
echo !first!
I am using Microsoft Windows XP [Version 5.1.2600]
Trying to do this.
Trying to create the variable dynamically and then read the value out of that variable in a loop.
#ECHO off
SET SQL1=TEST
SET SQL2=TEST1
SET SQL3=TEST2
SET SQL=SQL
SETLOCAL ENABLEDELAYEDEXPANSION
SET /A number=0
FOR /l %%A IN (1,1,3) DO (
SET /A number = number + 1
echo !number!
echo %SQL%!number!
)
endlocal
Output should be
1
test
2
test2
3
test3
I am getting
C:\temp>c.bat
1
SQL1
2
SQL2
3
SQL3
Please help!
Ugh.
First way (note that instead of your number variable, it uses the loop counter variable %%A):
#ECHO off
SET SQL1=TEST
SET SQL2=TEST1
SET SQL3=TEST2
SETLOCAL ENABLEDELAYEDEXPANSION
SET /A number=0
FOR /l %%A IN (1,1,3) DO (
SET /A number = number + 1
echo !number!
echo !SQL%%A!
)
endlocal
Second way (ugly but it does what you want):
#ECHO off
SET SQL1=TEST
SET SQL2=TEST1
SET SQL3=TEST2
SETLOCAL ENABLEDELAYEDEXPANSION
SET /A number=0
FOR /l %%A IN (1,1,3) DO (
SET /A number = number + 1
echo !number!
for %%i in (!number!) do (echo !SQL%%i!)
)
endlocal