sjoy
sjoy

Reputation: 502

How to use variables set in a sub called in a FOR loop, with delayed expansion

This code loops through the contents of "Fire" folder on PC, which contains several subfolders. For each subfolder it runs another FOR to look for a match to directories on a tablet. If no match found it calls subroutine :missing to set variables about the missing directory.

When I get back to main routine I'm unable to echo the vars set in the sub. I've tried many permutations of !name[%CNT%]! (doubling/tripling the % and !) but can't get it right. Hope someone can lend a hand.

@Echo off
SETLOCAL EnableDelayedExpansion
:main
Set /A CNT=0
    :: Fire folder contains dirs that may have been deleted from tablet. 
    For /F %%G IN ('dir /b %Fire%') DO (
        SET thisdir=%%G
        SET /A CNT+=1
            :: set command that will look for %%G on the tablet
            set cmd="adb shell ls /system/priv-app/!thisdir!"

            :: This loop returns nul if dir exists on device
            For /F "tokens=1* delims=:" %%g in ('!cmd!') do (set _N=%%h)
            If NOT "!_N!"=="" call :missing !thisdir! 

                    :: HERE'S THE PROBLEM: With this syntax I get    "CNT"     "CNT"
                    Echo AFTER THE CALL:        "!name[!CNT!]!"     "!pkg[!CNT!]!"

                    :: this displays:   "pkg[3]]
                    Echo AFTER THE CALL:        "%!name[!CNT!]%!"     [!pkg[!CNT!]!]
    )

:missing
:: Both %CNT% and !CNT! work here
    Set pkg[%CNT%]=%1

:: set friendly name for this dir
If "%1"=="com.name.video" set "name[%CNT%]=Video"
If "%1"=="com.name.games" set "name[%CNT%]=Games"
. . .
    :: THIS WORKS HERE IN THE SUB. HOW TO DISPLAY IN MAIN?                      
    Echo MISSING:       !name[%CNT%]!     (!pkg[%CNT%]!)

    :: Output: MISSING:          Video      (com.name.video)
exit /b

Upvotes: 1

Views: 57

Answers (3)

Xingxing Qiao
Xingxing Qiao

Reputation: 156

Maybe you can try this:

@echo off&SetLocal EnableDelayEdexpansion

set "name[1]=something"
set "a=1"

echo !name[%a%]!
rem echo %name[!a!]%
call echo !name[%a%]!
call echo %%name[!a!]%%
call echo %%name[%a%]%%
for %%a in (!a!) do (echo !name[%%a]!)

pause

Upvotes: 0

rojo
rojo

Reputation: 24466

In your first AFTER THE CALL line, your script will try to evaluate !name[! and then a string literal CNT and then !]! and so on. Since both !name[! and !]! are undefined, they evaluate to nothing and you're left with the string literal, CNT. Instead, you should convert the inner !CNT! to percent notation, so it can peacefully coexist with the outer delayed variable. You can accomplish this with a for loop.

for %%I in ("!CNT!") do echo !name[%%~I]!

... to avoid the conflicting exclamation marks. In your second AFTER THE CALL line, you attempt to begin a variable with %! while also ending it with %!. When using that sort of syntax, the ! has to be outside, and the % inside (or possibly vice-versa -- see Magoo's answer for an example). But since it's inside a parenthetical code block, it won't work like you want anyway. You need the delayed expansions. Use the for loop I described above.

By the way, don't use those :: pseudo-labels as comments within a parenthetical code block. Use rem instead. The :: can break things.

Upvotes: 1

Magoo
Magoo

Reputation: 79982

To display in main loop:

call Echo AFTER THE CALL:  "%%name[!CNT!]%%"     [%%pkg[!CNT!]%%]

Iassume you know not to use ::comments in a block and that your maun will run into your sub...

Upvotes: 1

Related Questions