Arrays, linked lists and other data structures in cmd.exe (batch) script Arrays, linked lists and other data structures in cmd.exe (batch) script arrays arrays

Arrays, linked lists and other data structures in cmd.exe (batch) script


Ok. I'll try to be as clear as possible to not be misunderstood...

In Windows Batch files a variable name should begin with a letter and may include any valid character, where valid characters are: #$'()*+,-.?@[]_`{}~ besides letters and digits.

This means that from the cmd.exe point of view, SET NORMAL_NAME=123 is exactly the same as SET A#$'()*+,-.?@[\]_{}~=123 and also the same as SET VECTOR[1]=123; all three are normal variables. This way, it is up to you to write variable names in the form of array elements:

set elem[1]=First elementset elem[2]=Second oneset elem[3]=The third one

This way, echo %elem[2]% will show Second one.

If you want to use another variable as index, you must know that the replacement of variables enclosed in percent symbols by their values is parsed from left to right; this means that:

set i=2echo %elem[%i%]%

doesn't give the desired result because it means: show the value of the elem[ variable, followed by i, followed by the value of the ] variable.

To solve this problem you must use Delayed Expansion, that is, insert setlocal EnableDelayedExpansion command at the beginning, enclose index variables in percent symbols, and enclose the array elements in exclamation marks:

setlocal EnableDelayedExpansionset elem[1]=First elementset elem[2]=Second oneset elem[3]=The third oneset i=2echo !elem[%i%]!

You may also use parameters of FOR commands as indexes: for /L %%i in (1,1,3) do echo !elem[%%i]!. You must use !index! to store values in array elements when the index is changed inside a FOR or IF: set elem[!index!]=New value. To get the value of an element when the index changes inside FOR/IF, enclose the element in double percent symbols and precede the command with call. For example, to move a range of array elements four places to the left:

for /L %%i in (%start%,1,%end%) do (   set /A j=%%i + 4   call set elem[%%i]=%%elem[!j!]%%)

Another way to achieve the previous process is to use an additional FOR command to change the delayed expansion of the index by an equivalent replaceable parameter, and then use the delayed expansion for the array element. This method runs faster than previous CALL:

for /L %%i in (%start%,1,%end%) do (   set /A j=%%i + 4   for %%j in (!j!) do set elem[%%i]=!elem[%%j]!)

This way, the Batch file behaves like it manages arrays. I think the important point here is not to discuss if Batch manages arrays or not, but the fact that you may manage arrays in Batch files in an equivalent way of other programming languages.

@echo offsetlocal EnableDelayedExpansionrem Create vector with names of daysset i=0for %%d in (Sunday Monday Tuesday Wednesday Thrusday Friday Saturday) do (   set /A i=i+1   set day[!i!]=%%d)rem Get current date and calculate DayOfWeekfor /F "tokens=1-3 delims=/" %%a in ("%date%") do (   set /A mm=10%%a %% 100, dd=10%%b %% 100, yy=%%c)if %mm% lss 3 set /A mm=mm+12, yy=yy-1set /A a=yy/100, b=a/4, c=2-a+b, e=36525*(yy+4716)/100, f=306*(mm+1)/10, jdn=c+dd+e+f-1523, dow=jdn %% 7 + 1echo Today is !day[%dow%]!, %date%

Note that index values are not limited to numbers, but they may be any string that contain valid characters; this point allows to define what in other programming languages are called associative arrays. At this answer there is a detailed explanation of the method used to solve a problem using an associative array. Note also that the space is a valid character in variable names, so you must pay attention to not insert spaces in variable names that may go unnoticed.

I elaborated on the reasons I have to use array notation in Batch files at this post.

In this post there is a Batch file that reads a text file and stores the indexes of the lines in a vector, then does a Buble Sort of vector elements based on line contents; the equivalent result is a sort over file contents.

In this post there is a basic Relational Data Base application in Batch based on indexes stored in files.

In this post there is a complete multiple linked-list application in Batch that assembles a large data structure taken from a subdirectory and displays it in the form of TREE command.


Windows shell scripting really isn't designed to work with arrays, let alone complex data structures. For the most part, everything's a string in the windows shell, but, there are some things you can do to "work with" arrays, like declaring n variables VAR_1, VAR_2, VAR_3... using a loop and filtering on the prefix VAR_, or creating a delimited string and then using the FOR construct that iterates over a delimited string.

Similarly, you can use the same basic idea to create a struct-like set of variables like ITEM_NAME, ITEM_DATA or w/e. I even found this link that talks about simulating an associative array in CMD.

It is all terribly hackish and inconvenient when it comes down to it. The command-line shell just wasn't designed for heavy programming. I agree with @MatteoItalia -- if you need serious scripting, use a real scripting language.


I made a bubble sort implementation in batch using pseudo-arrays a while ago.Not sure why you'd use it (although I will admit to doing so in another batch file) as it gets pretty slow as the list size increases. It was more to set myself a little challenge.Someone might find this useful.

:: Bubblesort:: Horribly inefficient for large lists:: Dave Johnson implementation 05/04/2013@echo offsetlocal enabledelayedexpansion:: Number of entries to populate and sortset maxvalue=50:: Fill a list of vars with Random numbers and print themfor /l %%a in (1,1,%maxvalue%) do (    set /a tosort%%a=!random!):: echo themset tosort:: Commence bubble sortEcho Sorting...set /a maxvalue-=1set iterations=0for /l %%a in (%maxvalue%,-1,1) do ( REM Decrease by 1 the number of checks each time as the top value will always float to the end    set hasswapped=0        for /l %%b in (1,1,%%a) do (            set /a next=%%b+1            set next=tosort!next!            set next=!next!            call :grabvalues tosort%%b !next!            rem echo comparing tosort%%b = !tosortvalue! and !next! = !nextvalue!            if !nextvalue! LSS !tosortvalue! (            rem set /a num_of_swaps+=1            rem echo Swapping !num_of_swaps!                set !next!=!tosortvalue!                set tosort%%b=!nextvalue!                set /a hasswapped+=1            )        )    set /a iterations+=1    if !hasswapped!==0 goto sorted)goto:eof:grabvaluesset tosortvalue=!%1!set nextvalue=!%2!goto:eof:sorted::nice one our kidset tosortvalue=echo Iterations required: %iterations%set tosortendlocal