Eu quero mudar uma variável de contador dentro de uma função de chamada.
No meu exemplo eu quero contar todas as subpastas (= count_all) e depois quero incrementar a contagem das subpastas que ela procedeu com sucesso (= 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
O código funciona, mas não entendo o comportamento do setlocal enabledelayedexpansion
. Quando coloco na chamada :process_subfolders
não consigo mais alterar as variáveis e não sei como retorná-las de acordo. De alguma forma, eu poderia defini-los no final da chamada endlocal & set "%2=whatever"
(ou algo assim), mas ainda não entendo quais variáveis são locais e quais não são.
Qual é a diferença entre count_all
, %count_all%
e !count_all!
e quando devo usar which?
Eu sugeriria usar o comando FOR /D .
Um pequeno exemplo de teste:
Quanto à diferença entre os vários operadores de substituição de variáveis, você não é o único que está confuso aqui.
A principal diferença é se o operador de substituição,
%
ou!
, está relacionado ao valor atual ou inicial da variável.A opção EnableDelayedExpansion faz com que as variáveis sejam expandidas na execução, e não no tempo de análise. Quando a expansão atrasada está em vigor, as variáveis podem ser lidas imediatamente usando
!variable_name!
. Using%variable_name%
continuará a mostrar o valor inicial que é expandido no início da linha, que pode ser diferente para loops.Adicionei ao meu código um
echo
comando que demonstra a diferença. Ele usa!count_all!
, porque usar%count_all%
resultaria no valor de quando ofor
comando foi iniciado, que é sempre0
. Mas%%i
não precisa do!
operador, pois está programado como variável do loop.Você encontrará uma explicação detalhada no seguinte post (resposta mais votada):
Como funcionam SETLOCAL e ENABLEDELAYEDEXPANSION?
Essa inconsistência dos dois operadores de substituição leva a uma confusão que nem sempre é resolvida apenas pela lógica. Às vezes, é necessário tentar e errar antes de acertar.