Search code examples
for-loopbatch-filevariablescmdcount

How to count from 1 to 50 and set each number as a variable in Batch file?


Good Day, I here a batch script that uses a function to operate

@echo off
setlocal enableDelayedExpansion
:INSTALLER

    
set "n1=7_Zip"
set "n2=Adobe_Products"
set "n3=Allavsoft"
set "n4=Astute_Graphics"
set "n5=AutoHotkey"
set "n6=Backup_and_Sync_from_Google"
set "n7=BlueStacks_5_Beta"
set "n8=CC_Cleaner"
set "n9=Core_Temp"
set "n10=CPUID_CPU-Z"
  

I'm having trouble because I want the variable n1 n2...10 to be dependent, Meaning I want it to be like this !n%c%! (where %c%is the number after n) so when I insert a new program between 2 programs the numbering will be moved. For example, I will insert the Notepad++ between CC_cleaner and Core_Temp. Now when I insert the Notepad++ its number will be the Old number of Core_Temp which is 9 and the New number of Core_Temp will be 10 and the New number of the CPUID_CPU-Z will be 11. I just can't figure out where I can get the variable 1 2 ... 11 to be substituted to the value of %c%. I'm thinking of a for loop that will count from 1 to 50 and set each number as a variable so I can Substitute those variables for the value of %c% but I don't know how to make it.

I'm also open to other options aside from for loop


Solution

  • use a function to define the array. In doing so, new values only need to be added to the list of parameter values the function is called with.

    Edit: I'm not sure whats unclear given the usage example provided and the description of the argument structure of the function, so heres a desciption of the functionality of the function:

    In your opening question, you manually define an array with the prefix n followed by numeric indexes one at a time:

    set "n1=7_Zip"
    set "n2=Adobe_Products"
    set "n3=Allavsoft"
    set "n4=Astute_Graphics"
    set "n5=AutoHotkey"
    set "n6=Backup_and_Sync_from_Google"
    set "n7=BlueStacks_5_Beta"
    set "n8=CC_Cleaner"
    set "n9=Core_Temp"
    set "n10=CPUID_CPU-Z"
    

    The above method of hard coding each value to an index makes adding values to the beginning / middle of the array time consuming as each n# has to be manually updated.

    Rather than hardcoding each value line by line, The function below takes a list (or series of lists) as parameters containing the arrays name (%1, the first argument) and the values to be defined to the array (all other arguments), assigns the list to a variable in order to seperate the array name from the values to be defined, then uses a For loop to iterate over the values, increment the arrays unique index, and then assigns the current value in the list to the appropriate index.

    This allows the above definitions to be achieved using the following call:

    Call :DefineArray n 7_Zip Adobe_Products Allavsoft Astute_Graphics AutoHotkey Backup_and_Sync_from_Google BlueStacks_5_Beta CC_Cleaner Core_Temp CPUID_CPU-Z
    

    Example output (with Set n.):

    n.1=7_Zip
    n.10=CPUID_CPU-Z
    n.2=Adobe_Products
    n.3=Allavsoft
    n.4=Astute_Graphics
    n.5=AutoHotkey
    n.6=Backup_and_Sync_from_Google
    n.7=BlueStacks_5_Beta
    n.8=CC_Cleaner
    n.9=Core_Temp
    

    Notes:

    • The function defines array variables using an additional . suffix to the arrays prefix name (IE: n.1 n.2 ...). This is done to allow differentiation of the array from other environment variables that begin with the same prefix as the arrays variable name when the Set command is being used.
    • The function does not zero the index count of the array when called. This allows calls to define values to be spread over multiple lines for easier maintenance and readablity.
    @Echo off
    
    :# prepare envarinoment for use of '!' expansion during code blocks
    :# '!' expansion allows access of variables whose name contains other variables
    :#     and provides protection against batch poison characters
     Setlocal EnableExtensions EnableDelayedExpansion
    
    :# Calls the label DefineArray with parameters; doublequoting any string containing
    :#     standard delimiters
     Call :DefineArray arrayname value1 "value 2"
    
    :# Display defined variables prefixed with arrayname
     Set arrayname
    Goto :Eof
    
    :# Function label name and arg structure
    :DefineArray groupname list of values
    
    :# Define all paramters to Params with leading whitespace used to remove groupname from parameter list.
     Set ^"Params= %*"
    
    :# Remove the groupname from the list of elements to be assigned
     Set "Params=!Params: %1 =!"
    
    :# Initialise array index variable specific to the groupname;
    :#     [If not already incremented]
    
     Set /A "%~1[i]+=0"
    
    :# iterate over Params list; increment group index count; Assign element
    :# to groupname.index
     For %%G in (!Params!)Do (
      Set /A "%~1[i]+=1"
      Set "%~1.!%~1[i]!=%%~G"
     )
    
    :# exit function
     Exit /b 0
    

    Note: The method used above will consume any ! characters present in values due to Delayed expansion.