2

I'm trying to check if files from an array exists. The array and the loop are working fine, but the if exists-line gives a syntaxerror. I tried different variations (%%list[%x%]%%, list[%x%], %%list[%%x%%]%%), but none of them works.

Question: Why is the if exists %%list[%x%]%% not working, but the call echo Check file: %%list[%x%]%% works?

Hint: I use this kind of "loop", because I want that the coded hasn't to be changed if the size of the array changes.

set list[0]="C:\file_a.txt"
set list[1]="C:\file_b.txt"
set list[2]="C:\file_c.txt"

set "found=0"
set "notfound=0"
set "x=0"
:SymLoop
if defined list[%x%] (

    call echo Check file: %%list[%x%]%%

    if exists %%list[%x%]%% (
        set /a "found+=1"
    ) else (
        set /a "notfound+=1"
    )

    set /a "x+=1"
    GOTO :SymLoop
)
echo %found%/%x% file found. %notfound% files missing!
PAUSE

Solved: The problem was the missing "Delayed Expansion" and in addition a typo (exists instead of exist).

netblognet
  • 1,951
  • 2
  • 20
  • 46
  • 2
    `if exists %%list[%x%]%%` cannot work as you need an additional layer of expansion; `call echo %%list[%x%]%%` works, because `call` introduces such a layer; `call if ...` does not work though, because `if` is a command that is recognised by the command interpreter before `call`; so the only solution is to use [delayed expansion](http://ss64.com/nt/delayedexpansion.html). Ah, and put quotes in: `if exists "!list[%x%]!"`... – aschipfl Dec 01 '17 at 09:29
  • 1
    By the way, you do not need to use a slow `goto` loop, you could create a loop like `for /F "delims=" %%x in ('set list[') do ( ... )`, which loops through all array elements (given that there is no other variable whose name begin with `list[`)... – aschipfl Dec 01 '17 at 09:34
  • @aschipfl - or simply `for /l` can be used and not worrying what other variables could exist. – npocmaka Dec 01 '17 at 09:37
  • @npocmaka but with `for /l` I had to define the length of the array in the loop. That's what I wanted to prohibit. – netblognet Dec 01 '17 at 09:40
  • 1
    @npocmaka, `for /L` requires the array size to be known. To make sure no disturbing variables exist, the following code could be placed before assigning the array: `for /L "delims==" %%x in ('set list[') do set "%%x="` – aschipfl Dec 01 '17 at 10:14
  • This management is fully explained at [this answer](https://stackoverflow.com/questions/10166386/arrays-linked-lists-and-other-data-structures-in-cmd-exe-batch-script/10167990#10167990) – Aacini Dec 01 '17 at 14:21

1 Answers1

1

try like this:

setlocal EnableDelayedExpansion
set list[0]="C:\file_a.txt"
set list[1]="C:\file_b.txt"
set list[2]="C:\file_c.txt"

set "found=0"
set "notfound=0"
set "x=0"
:SymLoop
if defined list[%x%] (

    echo Check file: !list[%x%]!

    if exist !list[%x%]! (
        set /a "found+=1"
    ) else (
        set /a "notfound+=1"
    )

    set /a "x+=1"
    GOTO :SymLoop
)
echo %found%/%x% file found. %notfound% files missing!
PAUSE
npocmaka
  • 55,367
  • 18
  • 148
  • 187