0

Hello I've a problem with this batch script , it does not work:

set OUTdir=../output

@echo on
:: ex  nFun  tol  M Nt print
::     nFun: numero di funzione test [1,...,7]
::     tol:  error tolerance
::     M:    ridotta di ordine 2*M+1
::     Nt:   Numero di valori della funzione inversa
::     print: 1 (to print the header) 2(to print the end of the header) 0 or nothing( to print just output values)

SET /A y=1
set /A max=16384

FOR /L %%x IN (32,1,%max%) DO (
 IF  %y% EQU 1 (
  ex 1 1e-9 %%x 25  %y% > %OUTdir%\out_F01_times_9.txt   
  set /A y=0) 
  ELSE (
  if  %y% EQU 0 if  %%x LSS %max% (  
    ex 1 1e-9 %%x 25 0  > %OUTdir%\out_F01_times_9.txt )
   ELSE (
    ex 1 1e-9 %%x 25 2  > %OUTdir%\out_F01_times_9.txt ) )
)

ex is a program and the other numbers are parameters by command line.

Could you help me? I'm trying to create a batch to execute ex program with different parameters.

The error is ELSE IS NOT RECOGNIZED AS EXTERNAL OR INTERNAL COMMAND

Linux
  • 3
  • 8
  • 1
    Maybe [this](https://stackoverflow.com/a/25073859/2861476) could help – MC ND May 25 '17 at 10:05
  • ok. But it seems that y variable is not update – Linux May 25 '17 at 10:25
  • 1
    You need to enable and apply [delayed expansion](http://ss64.com/nt/delayedexpansion.html) as you are writing *and* reading the variable within the same parenthesised block of code... – aschipfl May 25 '17 at 10:36
  • `SET /A` is used for arithmetic operations not to set numeric variables. You can just use `SET "y=1"` `set "max=16384"` and `set "y=0"`. – Compo May 25 '17 at 10:43
  • I would recommend you when comparing to use `""`, e.g., `IF "%y%" EQU "1"`. – dcg May 25 '17 at 11:29
  • @Compo Using set /a to set values is completely valid and has the advantage that you can set multiple values with only one command `set /a y=1,max=16384,z=y*max` –  May 25 '17 at 13:55
  • 1
    I never said it wasn't valid, and I'm fully aware of it's pro's and con's. In the context and structure of the script the OP was requiring help and advice with it wasn't necessary. – Compo May 25 '17 at 14:01

2 Answers2

0

You must put your ELSE clauses on the same line as the close-paren of your IF-clause actions (I most commonly see it as ) ELSE ( on a line by itself):

set OUTdir=../output

@echo on
:: ex  nFun  tol  M Nt print
::     nFun: numero di funzione test [1,...,7]
::     tol:  error tolerance
::     M:    ridotta di ordine 2*M+1
::     Nt:   Numero di valori della funzione inversa
::     print: 1 (to print the header) 2(to print the end of the header) 0 or nothing( to print just output values)

SET /A y=1
set /A max=16384

FOR /L %%x IN (32,1,%max%) DO (
 IF  %y% EQU 1 (
  ex 1 1e-9 %%x 25  %y% > %OUTdir%\out_F01_times_9.txt   
  set /A y=0 
  ) ELSE (
  if  %y% EQU 0 if  %%x LSS %max% (  
    ex 1 1e-9 %%x 25 0  > %OUTdir%\out_F01_times_9.txt
    ) ELSE (
    ex 1 1e-9 %%x 25 2  > %OUTdir%\out_F01_times_9.txt
    )
  )
)

You also do not need the /A when you are SETting a variable to a simple number; SET /A allows for mathematical operations in the SET command, e.g., SET /A Y=%M%*4 to set Y to four times the number stored in M.

Jeff Zeitlin
  • 9,773
  • 2
  • 21
  • 33
  • by the looks of the code, without testing, it does not seem like else is even needed here. can get away with IF's only, besides an else at the end.. – Gerhard May 25 '17 at 11:52
  • @GerhardBarnard - No, without the `ELSE`s, if Y starts out as 1, then both the Y=1 and Y=0 clauses will be executed, because after exiting the "then" block from the first test, it will test for Y=0 - which will be true, at that point. – Jeff Zeitlin May 25 '17 at 11:58
  • yeah, just noticed the `set /A=1` on the top. – Gerhard May 25 '17 at 12:10
0

As other answer/comments indicated, you need to place the closing parentheses accordingly to the C-K&R style, not the Lisp style as shown in the Brace placement part of the Indent Style Wikipedia article.

However, your code is over-complicate. You are using the y variable in the first IF %y% EQU 1 just to execute the first ex command once (that, BTW, require delayed expansion to work properly), and you are using the last if %%x LSS %max% just to execute the last ex command once. You may get the same result with this code, that don't require any if, so it should run faster:

set OUTdir=../output


SET /A max=16384, maxM1=max-1

(  ex 1 1e-9 32 25 1
   FOR /L %%x IN (33,1,%maxM1%) DO (
      ex 1 1e-9 %%x 25 0
   )
   ex 1 1e-9 %max% 25 2
) > %OUTdir%\out_F01_times_9.txt

Note that you may also enclose several commands in parentheses and use just one redirection for they all; this method not only looks clearer, but it is also more efficient/faster.

Aacini
  • 65,180
  • 12
  • 72
  • 108
  • Hello I've rewritten the code but step var is not updated: inline `SET /A max=16384, maxM1=8192, Nt=25, startM=16, M=1024, startNt=25, startNt1=startNt+1, maxNt=512, maxNt1=maxNt-1, step=32 SET "tol=1e-9" set "nfun=1" set "varpar=Mvar" ( ex %nfun% %tol% %startM% %Nt% %varpar% 1 FOR /L %%x IN (1,1,9) DO ( ex %nfun% %tol% %step% %Nt% %varpar% 0 set /A step = !step!*2 ) ex %nfun% %tol% %max% %Nt% %varpar% 2 ) > %OUTdir%\out_F01_times_9_M_var.txt endlocal` – Linux May 30 '17 at 14:49
  • Of course. Any variable modified _inside parentheses_ needs !delayed_expansion!, _excepting_ in `set /A` command! The `set /A step = step*2` operation may also be written in this simpler way: `set /A step*=2`; see `set /?`. In conclusion: **1.** Insert `setlocal EnableDelayedExpansion` at beginning. **2.** Change the `FOR` by this one: `FOR /L %%x IN (1,1,9) DO ( ex %nfun% %tol% !step! %Nt% %varpar% 0 set /A step*=2 )` – Aacini May 30 '17 at 20:25