cmdのforやif内値代入!setできない原因は遅延環境変数!
Windowsのコマンドプロンプト(以下cmd)を利用することで効率よく作業を行なえる。
batファイルにコマンドを記述して、バッチ処理を走らせたりして、便利ですよね。
特に私の勤めています会社では、Windowsタスクスケジューラを利用して、
ウェブサーバのデータを自動的に管理したりしています。
そんな便利なバッチ処理であるが、
cmdを使っていて、非常に困った経験がある。
for文やif文内で代入した変数が消える!?
まずは下記のソース文を見てほしい。
1 2 3 4 5 6 7 8 9 10 11 | @echo off rem 参照中のディレクトリ内のファイルを順に探索 for %%F in (*) do ( rem ファイル名を表示 set file= %%F echo %file% ) pause |
このソースはカレントディレクトリ内のファイル名をすべて取得して、
そのファイル名を一つずつ画面上に出力させるものです。
とまあこんな感じで、for文を使って、
順々にファイル名を取得して、表示させたいわけですが、
なぜか、取得しているはずのファイル名が画面上に出てこないんだ。
1 2 3 4 5 6 7 8 9 | ECHO は <OFF> です。 ECHO は <OFF> です。 ECHO は <OFF> です。 ECHO は <OFF> です。 ECHO は <OFF> です。 ECHO は <OFF> です。 ECHO は <OFF> です。 ECHO は <OFF> です。 続行するには何かキーを押してください . . . |
ECHO は <OFF> です。
このメッセージってechoさせた変数が初期化されて時に出るやつだ・・・。
まさか、ファイル名をセットできていない?
どう見ても、コマンドの構文が間違っているようには見えないし、
いったいどういうことなのだろうか?
変数の値が表示されない原因は何?
調べてみると、結構同じ悩みを抱えた人達がいるようだ。
for文のループなどを使っている時に
「あれ? 変数の値が変わらない?」という問題が多数寄せられていた。
for文やif文内で変数を扱うときには特に注意が必要らしい。
普通に変数を%で囲んでechoさせても結果が出てこない。
なぜ値が出てこないのか?
実は、for文内で変数に値はセットされている。
しかしながら、cmdの仕様上1行ずつコマンドを読み込む為、ラグのようなものが生じる。
原因は値が代入される前の状態を読みに行ってしまうからだ。
echoさせる値を代入しても、すぐにfor文が記述されている先頭行に処理が移るため、
値が代入される前の状態で表示されてしまうのだ。
もう一度ソース文を確認しよう。
1 2 3 4 5 6 7 8 9 10 11 | @echo off rem 参照中のディレクトリ内のファイルを順に探索 for %%F in (*) do ( rem ファイル名を表示 set file= %%F echo %file% ) pause |
4行目のforが開始された行が優先されるため、
for文内に含まれる処理は行われても、
forの開始時点の状態に戻されてしまう。
遅延環境変数を使って対処する方法がある
通常の処理では、私が行いたいことが行えません。
そこで、「遅延環境変数」というものを利用するといい。
遅延環境変数って何?
遅延環境変数とは、
名前の通り遅延して変数を評価するものです。
つまりはfor文の処理を遅延させ、echo文が読まれた後に、
forの最初の制御に移行してくれる便利な機能だ。
今回はfor文での例をご紹介しますが、
もちろん他の制御構文ifなどでも同様に扱うことができます。
しかし、この遅延環境変数ですがデフォルトではオフになっている。
有効にするには、cmdのオプションやレジストリの設定など行う必要がある。
そんなことは面倒だという人のために、
SETLOCALというコマンドで有効にすることもできます。
SETLOCALコマンドの使い方
以下のコマンドで囲んだ部分で遅延環境変数を利用することができます。
1 2 3 | SETLOCAL enabledelayedexpansion (処理) ENDLOCAL |
実際に遅延環境変数を利用すると下記のようになる。
1 2 3 4 5 6 7 8 9 10 11 12 13 | @echo off rem 遅延環境変数に対応させる setlocal ENABLEDELAYEDEXPANSION rem 参照中のディレクトリ内のファイルを順に探索 for %%F in (*) do ( rem ファイル名を表示 set file= %%F echo !file! ) endlocal pause |
9行目に注目して下さい。
echoさせる時、%で変数を囲まず、!で囲むと変数の値が表示されるようになります。
for文から外れた後でも利用できるので、便利ですよ~!
それにしても制御文内で変数を自由に扱えないという仕様はどうなんだろう・・・。
とりあえずはこれで解決だね!
最新記事 by よっき (全て見る)
- 「圧着」と「圧接」の違い!コネクタを使った効率的な配線作業! - 2019年10月26日
- 夏の暑さ対策は大丈夫?冷却性能抜群のおすすめCPUクーラー!メモリに干渉しない最強の商品を紹介! - 2018年5月1日
- 自作PC弐号機のケースを換装!SilverStone製のミニタワーで冷却性とかっこよさを追求! - 2018年3月11日
スポンサードリンク