I aim to modify a counter variable within a function call. Specifically, I need to keep track of the total number of subfolders (represented by “count_all”), and then increase the count of subfolders that the function successfully processed (indicated by “count_done”).
@echo off
cls
setlocal enableextensions enabledelayedexpansion
set /a "count_all=0"
set /a "count_done=0"
for /d /r %%i in (.\*) do call :process_subfolders "%%i"
if %count_all% EQU 0 (
echo No archives found.
) else (
set /a "counted=1"
for /d /r %%i in (.\*) do call :process_subfolders "%%i"
)
pause
endlocal
goto :eof
::___________________________________________________________________
:process_subfolders
set "folder=%~nx1"
pushd %folder%
if exist *.rar (
if !counted! equ 0 (
set /a "count_all+=1"
) else (
set /a "count_done+=1"
echo !count_done!: %folder%
rem ... do something with the rar files in this folder ...
rem ... for testing: use ping
ping 127.0.0.1 -n 2 > nul
set /a "percent=!count_done!*100/!count_all!"
title !percent!%% [!count_done!/!count_all!]
)
)
popd
exit /b
The code is functional, but I am unsure about the purpose and effects of the “setlocal enabledelayedexpansion
” command. When I apply it to the “call :process_subfolders
” function, I am unable to modify the variables and I am unsure how to properly return them. I found a potential solution by using “endlocal & set
“%2=whatever
“, but I am still confused about which variables are local and which ones are not.
Additionally, I am uncertain about the distinction between “count_all
“, “%count_all%
“, and “!count_all!
“, and when each should be used?
3 Answers
Introduction
The batch file shown above is used to keep track of subfolders and process them if they contain any RAR files. The script uses two counter variables, “count_all” and “count_done,” to keep track of the total number of subfolders and the number of subfolders that have been processed, respectively. The purpose of this blog post is to explain the functionality of the “setlocal enabledelayedexpansion
” command and the distinction between the different variable types used in the script.
The Purpose of setlocal enabledelayedexpansion
The “setlocal enabledelayedexpansion
” command is used to enable delayed expansion of variables in a batch file. Delayed expansion allows the use of variables within a batch file that are updated or changed during the execution of the script. Without delayed expansion, the variables are expanded at the beginning of the script, and any changes made to them during the execution of the script are not reflected in the expanded variables.
In the script shown above, delayed expansion is necessary because the variables “count_all” and “count_done” are updated within the “call :process_subfolders
” function. Without delayed expansion, the values of these variables would not be updated, and the script would not function as intended.
The Difference Between Local and Global Variables
In batch files, variables can be either local or global. Local variables are only accessible within the current scope, while global variables are accessible throughout the entire script. In the script shown above, the variables “count_all” and “count_done” are global variables because they are declared outside of any function or loop.
When a function is called in a batch file, any variables that are modified within the function are local variables, and their changes are not reflected outside of the function. To return the value of a local variable to the calling scope, the “endlocal & set
“%2=whatever
” command can be used, where “%2” is the name of the variable to be set and “whatever” is the value to be assigned to the variable.
Using Variables in Batch Files
In the script shown above, three different types of variables are used: “count_all,” “%count_all%
,” and “!count_all!
“. The difference between these variable types is based on their use within the script.
“count_all” is a global variable that is declared at the beginning of the script and is used to keep track of the total number of subfolders. This variable is modified within the “call :process_subfolders
” function and is accessed using the syntax “%count_all%
” to expand the value of the variable.
“%count_all%
” is used to expand the value of the “count_all” variable within the script. This syntax is used to expand the value of any variable in a batch file.
“!count_all!
” is used to expand the value of the “count_all” variable within the script when delayed expansion is enabled. This syntax is used to expand the value of any variable when delayed expansion is enabled.
Conclusion
In conclusion, the “setlocal enabledelayedexpansion
” command is used to enable delayed expansion of variables in a batch file. Delayed expansion allows the use of variables within a batch file that are updated or changed during the execution of the script. In the script shown above, the variables “count_all” and “count_done” are global variables that are modified within the “call :process_subfolders
” function, and their values are accessed using different variable types based on their use within the script. Understanding the functionality of delayed expansion and the distinction between local and global variables is essential for writing effective batch files.
setlocal enabledelayedexpansion
is a command that enables the use of delayed expansion in the script. Delayed expansion is a feature in batch scripts that allows you to use a different character to access the value of a variable, depending on when the variable is being accessed. The default character for accessing the value of a variable is the percent sign (%
).
With delayed expansion enabled, you can use the exclamation mark (!
) to access the value of a variable instead of the percent sign. This is useful when you want to modify the value of a variable within a loop and then use the modified value later in the same loop.
In your script, count_all
and count_done
are variables that are defined using set /a
. These variables are available within the script and can be accessed using the percent sign (%count_all%
and %count_done%
).
When setlocal enabledelayedexpansion
is used, the variables count_all
and count_done
can also be accessed using the exclamation mark (!count_all!
and !count_done!
).
To modify the value of a variable within a loop, you can use the following syntax:
set /a "count_all+=1"
This increments the value of count_all
by 1. You can also use the exclamation mark syntax to modify the value of a variable, like this:
set /a "count_all=!count_all!+1"
When you use setlocal enabledelayedexpansion
, you should use the exclamation mark syntax to access and modify the value of a variable within a loop.
To return the value of a variable from a subroutine (in this case, the process_subfolders
subroutine), you can use the endlocal
command to end the local environment and then use the set
command to set the value of the variable. For example:
endlocal & set "count_done=%count_done%"
This will set the value of count_done
to the value it had before the local environment was started.
I hope this helps. Let me know if you have any more questions!
I recommend using the FOR /D command.
Here is a brief example to test it out:
setlocal enabledelayedexpansion
set /a count_all=0
for /d /r %%i in (.\*) do (
echo !count_all! : %%i
set /a count_all+=1
)
echo all: %count_all%
Many people are also unsure about the differences between the various variable substitution operators. The primary distinction is whether the operator (%
or !
) pertains to the current or original value of the variable.
Enabling the EnableDelayedExpansion option causes variables to expand during execution, rather than during parsing. This means that variables can be read immediately using the syntax !variable_name!
.
Conversely, using %variable_name%
will display the original value that was expanded at the beginning of the line, which may differ in the case of loops. I included an echo command in my code that showcases this difference.
I utilized !count_all!
because %count_all%
would display the value at the start of the for command, which is always 0. However, %%i
does not require the !
operator since it is built-in as the loop variable.
The inconsistency of the two substitution operators can be confusing, and logic alone may not always resolve it. Sometimes, trial and error is necessary to get it right.