How can I setup an array variable in a DOS batch script? I would like to load it with a list of file names to process. I really would like to keep this as simple as possible. Thank you.
I figured it out:
set FILE_LIST=(file1.dll file2.exe file3.dll file4.dll file5.dll) set BIN_PATH="C:\Program Files\My App Folder\bin" set BAK_PATH="C:\Program Files\My App Folder\bin\Backups" set DEV_PATH="C:\My Dev Path\bin\Debug" for %%i in %FILE_LIST% do copy %BIN_PATH%\%%i %BAK_PATH% for %%i in %FILE_LIST% do copy %DEV_PATH%\%%i %BIN_PATH%
I did something like this several years ago, so it just took some figuring out. (btw, I hate reinventing the wheel.) Now that it's posted here, hopefully others will find it useful too.
Yes you can do arrays in batch. While they aren't exactly like arrays in C or VB, you CAN do it:
@echo off setlocal enabledelayedexpansion set arrayline=############ set arrayline=#..........# set arrayline=#..........# set arrayline=#..........# set arrayline=#..........# set arrayline=#..........# set arrayline=#..........# set arrayline=#..........# set arrayline=#..........# set arrayline=#..........# set arrayline=#..........# set arrayline=#..........# set arrayline=############ ::read it using a FOR /L statement for /l %%n in (0,1,12) do ( echo !arrayline[%%n]! ) pause
From Jakash3's Blog, Arrays in Batch describes how to emulate arrays in the command prompt.
A batch file named array.bat is included in the article, that contains a library of functions used to handle arrays. You will need to select the the text in the article and paste it inside the bat file.
For example, the following test script:
@echo off set book=Avatar set book=The Green Mile set book=The Count of Monte Cristo call array.bat add book Babo call array.bat len book length echo I have %length% books you can borrow. echo Pick one: echo. echo 0) Avatar echo 1) The Green Mile echo 2) The Count of Monte Cristo echo 3) Babo echo. set /p pick= call array.bat getitem book %pick% title echo. echo You picked %title%.
generates the following output:
This populates an array and prints it
You could use names1 names2 names3, rather than names names names by writing names!i! instead of names[!i!]. It produces the array by generating variable names. There isn't an array structure in batch. But it is as neat as any array structure, and populating or printing looks exactly like how one would populate or print an array in a proper language(that actually has the array structure!)
@echo off setlocal enabledelayedexpansion enableextensions set i=-1 for %%f in (bob, tom, joseph) do ( set /a i=!i!+1 set names[!i!]=%%f ) set lastindex=!i! for /L %%f in (0,1,!lastindex!) do ( echo !names[%%f]! )
c:\blah>a bob tom joseph c:\blah>
setlocal enabledelayedexpansion enableextensions with the !var! rather than %var% is necessary to prevent odd behavior, so that variables behave properly when within a FOR or an IF. It's an oddity with batch files. See
set /? where that is mentioned further.
This is what populates the array, and is pretty straight forward to anybody that knows about arrays. You could also do
names=joseph though one of the beauties of an array is the ability to populate an array with a loop, which is what i've done here.
for %%f in (bob, tom, joseph) do ( set /a i=!i!+1 set names[!i!]=%%f ) set lastindex=!i!
This displays the array. %%f if you echo it you'd see will go from 0 to the last index of the array, in steps of 1. so will print names names names
for /L %%f in (0,1,!lastindex!) do ( echo !names[%%f]! )
this is a small debug file i made a while a go to test te array from my tic tac tow game in BATCH / CMD. it can read and write to and from an array whitout going to big and complicated on the code.
using it is simple:
Writing to an array
- give it a file or modify it to import somting else.
- give the array a name.
- and your done.
Reading from an array
- Give the size of the array or part of it you whant to read.
- Put in the name of the array with %%a in the name
- and your done.
@echo off setlocal EnableDelayedExpansion set ID=0 :: Reader :: :: It reads the file called input.txt :: :: and stores it in a new variable that :: :: for everytime it goes over it it is a :: :: new ID (Slot in the array). :: For /F %%A in (input.txt) do ( set /a ID=ID+1 set Input!ID!= %%A echo !ID! : %%A ) :: Writer :: :: this is to read all Slots in the array :: :: and puts it on the screen. :: for /L %%a in (1,1,!ID!) do ( echo !Input%%a! ) pause>nul
For what you want to do, how about using an input variable for each file name, which you can pick up with the %1 %2 etc. variables eg: mybat.bat file1.nam file2.nam etc..
You can then use these variables in a loop but only need to use %1 as the main parameter as you can use SHIFT to bring the other variables into the %1 'position', having a test for null (end of variables) with something like IF "X%1" == "X"
:LOOP IF "X%1" == "X" GOTO DONE COPY %1 C:\TARGET.DIR SHIFT GOTO LOOP :DONE
If you save the list of files to filelist.txt, you can get
FOR to read and process each line of the file, such as
FOR /F "delims=|" %i IN (filelist.txt) DO @echo %i
to print each line of a file (up to the first "|" in the line. If you don't specify your own delimiter, space and tab will be used, so unless your paths have no spaces, you need to specify a character that will not appear in the file to get complete lines).
In one of your comments to an answer you say,
I am doing development work, and due to the complex nature of the application every time and want to test a build (which is often) I have to copy five files from the build binary directory to the install binary directory. This gets tedious. Right now, I have the file names hard-coded into my batch script, but I would like to put them into an array to make the script easier to maintain.
I believe that what you are looking for is a Makefile, and possibly cygwin to give you a decent shell (bash, or whatever your flavour).
Replace strings and letter in text.
Try for loop by expanding text to a for body and replacing var with var. Drag and drop text file so %1 is user input by invoking set command.
@echo off setlocal EnableDelayedExpansion set /p a= enter letter to change: set /p b= letter to change to: set /p input=<%1 for /f %%c in ("!input:~!") do ( set "code=!input:%a%=%b%!" echo !code!>myfile.txt )
Something like this in a batch file? Select a file in a folder. << is comment, no code
:selectapk SETLOCAL ENABLEDELAYEDEXPANSION << DELAYED EXPANSION on for counter in For loop SET /A MAXITEM=0 Echo. Echo Found these APK files in "add_apk_here" folder. Echo. For %%a in (add_apk_here/*.apk) do ( Set /A MAXITEM+=1 Set MENUITEM!MAXITEM!=%%a << Fill n local env vars, one for each file, called MENUITEM1...n Echo !MAXITEM!. %%a ) Echo. If !MAXITEM!==0 Echo No APK in "add_apk_here" folder & call :delay & Goto start << No apk files then go back SET /P CHOICE=Select APK to work on: SET MENUITEM=!MENUITEM%CHOICE%! << Get the stored filename from MENUITEMx SETLOCAL DISABLEDELAYEDEXPANSION << Very important for next ENDLOCAL that doesn't like the delayedexpansion var ENDLOCAL & SET apk=%MENUITEM% << put the local MENUITEM var into the global apk var goto start :delay REM %1 like Call :delay 5 SETLOCAL SET N=%1 If Not Defined N Set N=2 Ping -n %N% -w 1000 127.255.255.255 > nul ENDLOCAL Exit /b
You can't really do an array in the command prompt (and also it's not really DOS unless you are running Windows 3.1). However, you can do set-based processing with the FOR command.
To create the list of files to be processed, you can manually create a text file to be processed, or use the
dir /b <mask> command inside the FOR loop.
Something I learned the hard way with FOR - you need to use a SINGLE CHARACTER variable as your cursor!
Check out the Microsoft documentation on the FOR batch command. You can use FOR to iterate over a set of directories, files in a directory, or files in a directory and all of its sub-directories.
By default FOR handles set or just files:
FOR %f IN (*.txt) DO ECHO %f
Or, for recursive:
FOR /R %f IN (*.txt) DO ECHO %f
or, for just directories:
FOR /D %d DO ECHO %d