#1 03 Mar 2019 11:59

Rekrul
Member
Registered: 17 Apr 2016
Posts: 32

Using () to group commands: Something else that doesn't work properly

I give up!

Every time I think I've learned how to use a command/feature in scripts, it never works the way common sense tells you it should.

My latest problem: I want to make a subroutine that toggles the value of a variable. If the value is set, it clears it. If it's not set, it sets it. This will eventually be part of a larger script, but for now, I'm just trying (unsuccessfully) to get this part to work. The script is run with a single parameter on the command line, which is copied to the variable %test%.

Here is my code;

echo off
SETLOCAL EnableDelayedExpansion
set test=%1
:menu
@echo.
@echo 1) toggle %test%
@echo.
@echo 2) Exit
@echo.
C:\Commands\choice /c12 Please choose [1-2]: /n
if errorlevel 2 goto exit
if errorlevel 1 goto toggle

:toggle
if %test%==%1 (
set test=
goto menu
)

if [%test%]==[] (
set test=%1
goto menu
)

:exit
exit

First I test to see if %test% equals what was entered on the command line as a parameter. If so, I clear the variable and jump back to the menu. The second part is supposed to test for an empty variable and set it, then jump back to the menu. That's what's supposed to happen. Of course since nothing in the scripting language works the way you think it will, it doesn't work.

Clearing the variable works fine. When you try to toggle it again, it says "( was unexpected at this time." and exits.

What arcane rule have I broken? Does some special situation apply if I have two IF statements in a row? Do I need to use some other symbol to group commands when testing for an empty variable? Is the moon not aligned correctly???

Somewhere a Microsoft programmer is laughing his ass off watching people like me try to figure out why nothing seems to follow the rules. I followed the examples for testing for an empty variable exactly. I followed the examples for using parenthesis exactly. Common sense says it should work. It doesn't.

Is there some guide on the net that explains all the exceptions to the normal rules?

Offline

#2 03 Mar 2019 13:30

Simon Sheppard
Super Administrator
Registered: 27 Aug 2005
Posts: 1,029
Website

Re: Using () to group commands: Something else that doesn't work properly

The problem in this script is that the command 'set test=' does not clear the value of the variable, which you might expect from using any other more sensible language, but instead deletes the variable completely.
You can test this by adding in a line:

IF DEFINED test Echo The variable test does exist.

The effect this has is that the line

if %test%==%1 (

will fail whenever %test% does not exist.

On the command line ECHO %nonexistentvariable%
will return the raw text:
%nonexistentvariable%
but in a batch file ECHO %nonexistentvariable% just returns nothing and this causes problems for the IF comparison.

Surrounding the variable with [ ] means that there is always something for the IF command to compare

if [%test%]==[]

evaluates to

if []==[]

rather than

if ==[]

See here for more https://ss64.com/nt/if.html#exist

Offline

#3 04 Mar 2019 01:34

Rekrul
Member
Registered: 17 Apr 2016
Posts: 32

Re: Using () to group commands: Something else that doesn't work properly

Simon Sheppard wrote:

The problem in this script is that the command 'set test=' does not clear the value of the variable, which you might expect from using any other more sensible language, but instead deletes the variable completely.

Thank you for the explanation.

This script, like many I write, is meant to be used from within a file manager (Total Commander to be specific) to process files with an external program. I pass the parameter for the destination directory to it so that the files are processed from the source directory to the destination directory by including that parameter as part of the command lines. However sometimes I want them to go to the same directory. I could just display the same directory in both windows, which would have the same effect, but I wanted to make my script more elegant. Besides, if I forget to set up the directories ahead of time, I have to exit the script, set them up, then run it again.

I also could have made two copies of each command, one with the destination directory parameter and one without, and then executed the appropriate one based on the value of another variable, but that's also not very elegant.

I figured the most elegant way would to set or clear the value of a variable so that the same command does both. Also, I like adding options to make the script as flexible as possible. I don't know how to write actual programs for anything other than the C64, so this is the next best thing.

Based on the information you provided, I've amended my toggle routine to check for %test% being undefined and set it if it is. It works now and I've folded it into the larger script (which already worked, but lacked the toggle option).

Thanks again. smile

Offline

#4 04 Mar 2019 14:43

bluesxman
Member
From: UK
Registered: 29 Dec 2006
Posts: 1,090

Re: Using () to group commands: Something else that doesn't work properly

What arcane rule have I broken?

The fairly standard rule of protecting your variables by escaping/quoting smile  That said cmd variables (and quoting thereof – quoting in general to be fair) have some some minor peculiarities – but I shan't dig into all that now.

Notwithstanding Simon's very valid advice (IF DEFINED is very useful, and most likely the correct approach in this scenario), I would consider it to be good practice to always, always, always use double quotes to protect strings you are comparing (note: specifically strings, if you're trying to less-than/greater-than compare quoted numerics, you may get unexpected results.)

This simple step will guard against: empty variables, strings containing spaces, and special characters (with caveats).  In your example, I think this would have sidestepped the issue you describe:

:toggle
if "%test%" EQU "%~1" (
set "test="
goto menu
)

Note: The ~ in %~1 will remove any surrounding double quotes (which we then re-add to ensure they are there to make the comparison valid).

Last edited by bluesxman (04 Mar 2019 14:47)


cmd | *sh | Ruby | Chef

Offline

#5 05 Mar 2019 03:48

Rekrul
Member
Registered: 17 Apr 2016
Posts: 32

Re: Using () to group commands: Something else that doesn't work properly

To anyone who read my latest post; Never mind, I made a dumb mistake. Sometimes I'm not too bright.  roll

Last edited by Rekrul (05 Mar 2019 05:52)

Offline

Board footer

Powered by FluxBB