呼び出し関数内のカウンター変数を変更したい。
私の例では、すべてのサブフォルダー(= count_all)をカウントし、その後、正常に進行したサブフォルダー(= 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
コードは機能しますが、setlocal enabledelayedexpansion
の動作がわかりません。 :process_subfolders
の呼び出しに入れると、変数を変更できなくなり、それに応じて変数を返す方法がわかりません。どういうわけか、endlocal & set "%2=whatever"
(またはこのようなもの)によって呼び出しの最後にそれらを設定できましたが、どの変数がローカルでどれがローカルでないかはまだわかりません。
count_all
、%count_all%
、!count_all!
の違いは何ですか?いつどちらを使用する必要がありますか?
FOR/Dコマンド を使用することをお勧めします。
小さなテスト例:
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%
さまざまな変数置換演算子の違いについては、ここで混乱しているのはあなただけではありません。
主な違いは、置換演算子%
または!
が、変数の現在の値と初期値のどちらに関連するかです。
EnableDelayedExpansionオプション により、変数は解析時ではなく実行時に展開されます。遅延展開が有効な場合、変数は!variable_name!
を使用してすぐに読み取ることができます。 %variable_name%
を使用すると、行の先頭で展開される初期値が引き続き表示されます。これは、ループでは異なる場合があります。
違いを示すecho
コマンドをコードに追加しました。 !count_all!
を使用すると、for
コマンドが開始されたときと同じ値になり、常に%count_all%
になるため、0
を使用します。ただし、%%i
は、ループ変数としてプログラムされているため、!
演算子は必要ありません。
あなたは次の投稿(最も賛成された答え)で詳細な説明を見つけるでしょう:
SETLOCALおよびENABLEDELAYEDEXPANSIONはどのように機能しますか?
2つの置換演算子のこの不一致は、論理だけで常に解決されるとは限らない混乱につながります。正しく理解する前に試行錯誤が必要な場合があります。