まず、バッチスクリプトの文法は、一般のプログラミング言語の常識が通じない部分があるので、
・バッチスクリプトは簡単なケースだけしか使わない
・じっくりバッチスクリプトの文法を理解して熟練者になる
のどちらの方針で臨むかを最初に決めた方が良いです。
このレベルの処理をするなら、バッチスクリプトの熟練者を目指すのでなければ、他の言語をお勧めします。
・PowerShell
・VBScript (廃止予定なので、5年、10年後に使えなくなってもいい場合)
・OfficeのVBA
・WSL1またはWSL2 の bash等(デフォルトでは未インストールのはずなのでMSからインストール要)
・Windows非標準の各種プログラミング言語(インストール可能なら)
あるいは、後出の「案2」だとバッチスクリプトでもそれほど熟練者じゃなくてもいいかも。そんな気が強くしてきました。
以下、バッチスクリプトでやる場合の説明。
「環境変数」は「変数」とついてますが、一般のプログラミング言語の変数とは少し違います。
上記を実行してもHENSU1、HENSU2には「0」が格納されていて
とお書きですが、掲載のコードには%HENSU1%
%HENSU2%
がないので、おそらく、コピペミスで、実際にHENSU2
の値を確認したのは、
CMD
1rem 初期化
2set OUTPUT_PATH=D:\TEST
3set HENSU1=0
4set HENSU2=0
5
6for %%a in (*.pdf) do (
7
8 for /f "delims=_ tokens=1-2" %%A in ("%%a") do (
9 set HENSU1=%%A
10 set HENSU2=%%B
11 echo 1:%OUTPUT_PATH%\%HENSU2:~0,4%
12 echo 2:%OUTPUT_PATH%\%HENSU2:~0,4%\%%A
13 if not exist %OUTPUT_PATH%\%HENSU2:~0,4% (
14 mkdir %OUTPUT_PATH%\%HENSU2:~0,4%
15 )
16 )
17)
のようなコードだったのではないかと思います。
6行目のfor
から末尾の)
までが1つの大きな文です。%HENSU2%
や%HENSU2:~0,4%
の値取り出しは、一般の言語のようにその文に制御か移った時ではなくて、6行目のfor
から末尾までの大きな1文の構文解析の直前に行われます。この時点では値は0
なので、そのように変数名が値0
に置き換わります。その次にfor文が実行されます。C等をご存じなら文単位ではありますが#define
で定義するマクロみたいなものと思ってください(構文解析前に置換されるという意味で)。
このことは、set /?
で表示される環境変数についての説明の後半に例文付きで分かり易く説明されています。
対策としては、
案1:set /?
に出てくる「遅延環境変数の展開」を使う(普通の言語の「変数」と同じに使える))
案2:大きな文を作らず、小さい文を沢山並べる
の2通りあります。
案1の方針だと、
CMD
1rem ↓ 案1だとこのsetlocalが重要
2setlocal enabledelayedexpansion
3
4set OUTPUT_PATH=D:\TEST
5set HENSU1=0
6set HENSU2=0
7
8for %%a in (*.pdf) do (
9 for /f "delims=_ tokens=1-2" %%A in ("%%a") do (
10 set HENSU1=%%A
11 set HENSU2=%%B
12 echo 1:%OUTPUT_PATH%\!HENSU2:~0,4!
13 echo 2:%OUTPUT_PATH%\!HENSU2:~0,4!\%%A
14 if not exist "%OUTPUT_PATH%\!HENSU2:~0,4!" (
15 mkdir %OUTPUT_PATH%\!HENSU2:~0,4!
16 )
17 )
18)
if not exist
のif文の構文解析は、!HENSU2:~0,4!
の変数展開の前に行われるので、ファイル名の所を二重引用符で囲む必要があります(これは構文解析時にはクォートされてないカンマなどは空白扱いされるため)。案1だと、こういう細かい配慮が必要になるケースがあります。
私自身は案2を使うことが多いのですが、案2は、「複数の文をまとめる括弧(
)
を使わない」、あるいは厳密には、「複数の文をまとめる括弧(
)
の中では括弧内で更新される環境変数の%
による参照をしない」ということで、
CMD
1前略
2for %%a in (*.pdf) do (
3 for /f "delims=_ tokens=1-2" %%A in ("%%a") do call :FOO %%a %%A %%~B
4)
5exit /b
6
7:FOO
8rem ↓このFILENAMEが %%a 相当
9set FILENAME=%1
10set HENSU1=%2
11set HENSU2=%3
12以下略
のようにforの中味をサブルーチン:FOO
にして、:FOO
の中では文をまとめる括弧を使わずに書きます。
なお、%%B:~0,4%
のような、「forの制御変数」に対しての部分文字列取り出しや文字列置換機能はありません。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2024/07/16 04:04
2024/07/16 08:58 編集