You are not logged in.
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
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
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.
Offline
What arcane rule have I broken?
The fairly standard rule of protecting your variables by escaping/quoting 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
To anyone who read my latest post; Never mind, I made a dumb mistake. Sometimes I'm not too bright.
Last edited by Rekrul (05 Mar 2019 05:52)
Offline