Parentheses in Batch Files

7.7k views Asked by At

Something rather odd happening with the parentheses for this code:

Setlocal EnableDelayedExpansion
MyFOLDER=
FOR %%B IN (c,d,e,f,g) DO (@%%B: 2>nul && set z=%%B <nul if exist %z%\
(if %MYFOLDER%==[] (echo %z%
)
)
)

The above compiles, but this doesn't:

Setlocal EnableDelayedExpansion
MyFOLDER=
FOR %%B IN (c,d,e,f,g) DO (@%%B: 2>nul && set z=%%B <nul if exist %z%\
(if %MYFOLDER%==[] (
echo %z%
)
)
)

Nor this

Setlocal EnableDelayedExpansion
MyFOLDER=
FOR %%B IN (c,d,e,f,g) DO (@%%B: 2>nul && set z=%%B <nul if exist %z%\
(if %MYFOLDER%==[]
(
echo %z%
)
)
)

nor any other combination where "echo %z%" is below the (if MYFOLDER) line. Is there anything in the "FOR" line that is suspect?

2

There are 2 answers

4
Laurie Stearn On BEST ANSWER

This is an updated version of the above codeblock with a description of what is intended. I think it is better to post this as a solution rather than clog up the OP or edit it any further.

The script is supposed to search all NTFS drive candidates for "common\MYFOLDER". If the first occurrence of "common\MYFOLDER" on a drive is located, do stuff with it, and continue the search for the same on other drives. The user is warned of this and can back out to :ENDSCRIPT if desired. The assembler still aborts in a cmd window at "if exist %%B:" with "%%B is unexpected at this time"

Edit: Still bombs out still at the first for I think. How is the error viewed? Is it true that if copied to existing cmd window all the nested "!!"s must be replaced with "!"

Edit2: We get "'else' is not recognized as a internal or external command..." Might it be a problem with the GOTOs?

Edit3: ") else (" is required.

Setlocal EnableDelayedExpansion
set CURRDRIVE=B
SET MYFOLDER=

:SEARCHDRIVES



for %%B in (B C D E F G) do (
if exist %%B: (
%%B:
if NOT DEFINED MYFOLDER (
for /d /r %%c in (*) do (
if /i %%pc==\common\MYFOLDER\ (
set MYFOLDER=%%c GOTO GOTMYFOLDER))
) else (
if !CURRDRIVE!==%%B (
%%B:
for /d /r ... %%c in (*) do (
if /i %%pc===\common\MYFOLDER\ (
set MYFOLDER=%%c
color C4
SET /P deletefiles="There appears to be a duplicate mirrored drive. Do you wish to remove files on this drive as well? N will quit the script. (Y/N)"
echo deletefiles & echo. & echo "While the script runs, this message will appear for every fixed drive {ABCDEFG} detected containing a duplicate MYFOLDER directory."
if /i !deletefiles!==n GOTO FINISH
GOTO GOTMYFOLDER)
)
)
)
)
REM Exist Drive
)
REM Drives Loop



if DEFINED MYFOLDER (
GOTO FINISH
) else (
echo No Nonsense installed on this computer
pause
GOTO ENDSCRIPT)





:GOTMYFOLDER

cd /d %CURRDRIVE%:\
cd %MYFOLDER%

REM DO STUFF WITH MYFOLDER

if %CURRDRIVE%==B (
set CURRDRIVE=C
GOTO SEARCHDRIVES)
if %CURRDRIVE%==C (
set CURRDRIVE=D
GOTO SEARCHDRIVES)
if %CURRDRIVE%==D (
set CURRDRIVE=E
GOTO SEARCHDRIVES)
if %CURRDRIVE%==E (
set CURRDRIVE=F
GOTO SEARCHDRIVES)
if %CURRDRIVE%==F (
set CURRDRIVE=G
GOTO SEARCHDRIVES)

:FINISH
REM BLAH
:ENDSCRIPT
REM BLAH
1
mojo On

I see a few problems in spite of having no understanding of the goal.

You define a variable using SET (e.g. SET MyFolder=). In the Unix shells, you just say MyFOLDER=, but not in CMD.

The IF comparison of MYFOLDER (which should be done with == not =) is probably meaningless because you're not doing it in a way that will use the contents of the variable. You're just comparing the literal string MYFOLDER to the literal string []. This comparison will always be false and never change throughout the course of script execution.

You are making an assignment inside parentheses (the entire contents of which are evaluated all at once, including normal variable substitution) and then attempting to access that variable inside the same "block" (CMD doesn't really have well-defined syntax, but it's at least similar to a block). What will happen is that the %z% will be evaluated the moment the (...) is evaluated and, in this script, it will be empty and replaced with nothing. The subsequent IF EXIST will eat the next thing you give it, which is the parenthetical expression. I'm not able to predict what will really happen there.

I don't know why you're assigning %%B to z and then using z in a comparison. Why not just use %%B? %%B at least will use delayed expansion.

You've enabled Delayed Expansion, but you haven't used it (except for the FOR variable which is always delayed whether you turn on delayed expansion or not). To use delayed expansion, you have to surround the variable with bangs (!) instead of the normal percent (%). So, in the case of z, or MYFOLDER, it would become !z! and !MYFOLDER! respectively. Accessing variables this way is absolutely essential inside a parenthetical "block" if you assign a value to a variable within that same block.

I'd offer a revision of your script, but I'm too dull to understand what you're trying to accomplish.