[前の記事]« WindowsへTELNETログインするまでをバッチ処理で自動化したい
[次の記事][NT系]回数を確認しながらコマンドを実行し、成功したらループから抜ける処理 »

関連オンラインソフト配布サイト:
Vector>ダウンロード(top) |>MS-DOSまたは汎用 | >WindowsVista/XP/2000/NT

▲カテゴリー「IF(結果の検査、条件分岐)」索引へ
▲カテゴリー「遅延環境変数の展開」索引へ

( )内での環境変数を使った条件判断がうまく動かない

450.
DOSでの変数設定
2004年05月11日(火) 23時26分
さみ
あるフォルダ配下にある複数のサブフォルダに対して、順次以下の動作を行うバッチを作成しようとしています。

・サブフォルダ配下の start.dat に内容があり、end.dat には
 内容がない状態であれば(※1)、data.dat を data_save.dat に
 コピーする。

以下のDOSコマンドを書いてみたのですが、(※1)の判断がうまく出来ません。
-----------------------------------------------------
for /F %%a in ('dir /ad /b') do (

  echo "%%a"
  cd %%a

  if exist start.dat (
    if exist end.dat (

      for /F "tokens=1*" %%s in (start.dat) do set stext=%%s
      for /F "tokens=1*" %%e in (end.dat)   do set etext=%%e

      if not "%stext%"=="" (
        if "%etext%"=="" (
          echo Match!
REM       copy data.dat data_save.dat
        )
      )
    )
  )
  cd ..
REM  set stext=
REM  set etext=
)
-----------------------------------------------------

実行フォルダ
 + AAA
 | +- start.dat 1byte
 | +- end.dat  0byte
  + BBB
   +- start.dat 0byte
   +- end.dat  0byte

という状態で実行しました。
#期待としては、AAAのフォルダを処理する際にのみ「Match!」が表示される。

ところが1回目の実行ではどちらのフォルダもMatch!が表示されず、2回目はどちらも表示されてしまいます。
変数がクリアされていない成果と思い、上記でREMでコメントアウトしているsetの箇所を有効にすると、まったくMatch!が表示されなくなってしまいました。

何が問題か、お分かりの方がいらっしゃいましたら教えていただけませんでしょうか。

環境はWin2000Pro の DOS 5.00.2195です。
452.
Re:DOSでの変数設定
2004年05月12日(水) 09時45分
YanaKen
さみさん こんにちは。

 バッチ処理中の環境変数は、(標準の動作では)「その行が読み取られた時点で」まず実際の値に展開され、展開された結果が実行されます(詳しくは set /? のうしろのほうをご覧ください)。
 お書きになったサンプルでいうと、下記はすべて論理的には1つの「if文」内に存在するため、処理が始まる時点で環境変数 stextと etext がすでに「実際の値」(たとえば空の文字列)に置き換わってしまっています。

実際に実行される内容例:
set stext="" & set etext=""
if exist start.dat (
 if exist end.dat (
  for /F "tokens=1*" %%s in (start.dat) do set stext=%%s
  for /F "tokens=1*" %%e in (end.dat) do set etext=%%e
  if not ""=="" (
   if ""=="" (
   echo Match!
   )
  )
 )
)

 上記の場合だと、if not ""=="" は必ずfalseですから、その先が実行されることはない(したがって、メッセージ「Match!」は表示されない)ことになります。
 この動作が期待したものと異なる場合には、次の2つの回避方法が考えられます。
・環境変数の展開を遅延させるコマンド・プロンプト起動時オプション CMD /V:ON を利用する。
・環境変数への設定結果を判定する処理は、(GOTOやCALLなどを活用して)必ず独立した行にする。

※この掲示板でも過去に何度かこの話題が出てきていますので、参考にどうぞ。
http://fpcu.on.coocan.jp/dosvcmd/bbs/log/cat3/set_path/cat51/1-0461.html
http://fpcu.on.coocan.jp/dosvcmd/bbs/log/cat3/set_path/cat51/3-0092.html

<補足>
>ところが1回目の実行ではどちらのフォルダもMatch!が表示されず、2回目はどちらも表示されてしまいます。
>変数がクリアされていない成果と思い、上記でREMでコメントアウトしているsetの箇所を有効にすると、まったくMatch!が表示されなくなってしまいました。
 ご想像の通り「前回のバッチ実行時に設定された変数をクリアしていなかった」ことが影響したのでしょう。

YanaKen
454.
Re2:DOSでの変数設定
2004年05月12日(水) 12時02分
さみ
YanaKenさん、こんにちは。
早速の丁寧なアドバイスありがとうございます。

>・環境変数への設定結果を判定する処理は、(GOTOやCALLなどを活用して)必ず独立した行にする。

GOTOを利用するようにもしてみたのですが、これも何か書き方が悪いのか、Forループを抜けてしまったりと上手くいきませんでした。

>※この掲示板でも過去に何度かこの話題が出てきていますので、参考にどうぞ。

過去の情報を参考に、setlocal して遅延環境変数を用いることにより、あっさりうまくいきました。
本当に助かりました。ありがとうございました。
458.
Re3:DOSでの変数設定
2004年05月13日(木) 01時47分
oo
>YanaKenさん、こんにちは。
>早速の丁寧なアドバイスありがとうございます。

>>・環境変数への設定結果を判定する処理は、(GOTOやCALLなどを活用して)必ず独立した行にする。

>GOTOを利用するようにもしてみたのですが、これも何か書き方が悪いのか、Forループを抜けてしまったりと上手くいきませんでした。

>>※この掲示板でも過去に何度かこの話題が出てきていますので、参考にどうぞ。

>過去の情報を参考に、setlocal して遅延環境変数を用いることにより、あっさりうまくいきました。
>本当に助かりました。ありがとうございました。

for文のdoの後の( ) 内でgotoを使うと、( ) 内へのgotoであってもfor文の外に飛び出したと見なされるようなのでだめです。使うとしたらCALLですね。

ファイルのサイズがゼロかどうかの判断をするなら、
for %%s in (start.dat) do if not %%~zs==0 (
 for %%e in (end.dat) do if %%~ze==0 (
   echo Match!
   rem copy data.dat data_save.dat
))
が直接的かと思います。
あと、
for /F "tokens=1*" %%s in 
は、1番目のトークンを%%sに入れて2番目以降のトークンを%%tに入れるという意味ですが、誤解はありませんか?%%sに1行全部入れたければ、"delims=" です。"tokens=*" でもほぼ同じですが行頭の空白がカットされます。
462.
Re4:DOSでの変数設定
2004年05月13日(木) 13時04分
さみ
ooさん、ご教示ありがとうございます。

>for文のdoの後の( ) 内でgotoを使うと、( ) 内へのgotoであってもfor文の外に飛び出したと見なされるようなのでだめです。使うとしたらCALLですね。

そうですそうです。forループ内の1回目の処理しか行いませんでした。

>ファイルのサイズがゼロかどうかの判断をするなら、
>for %%s in (start.dat) do if not %%~zs==0 (
> for %%e in (end.dat) do if %%~ze==0 (
>   echo Match!
>   rem copy data.dat data_save.dat
>))
>が直接的かと思います。

「%%~ze」なんて指定ができるのですね。勉強になります。

>あと、
>for /F "tokens=1*" %%s in 
>は、1番目のトークンを%%sに入れて2番目以降のトークンを%%tに入れるという意味ですが、誤解はありませんか?%%sに1行全部入れたければ、"delims=" です。"tokens=*" でもほぼ同じですが行頭の空白がカットされます。

しっかり誤解しておりました。(^^;)

今週は出張中で時間と環境が無いのですが、教えたいただいた方法も試してみます。
ありがとうございました。
 
 


カテゴリー「IF(結果の検査、条件分岐)」索引へ
カテゴリー「遅延環境変数の展開」索引へ

 

カテゴリー一覧

FPCU/FPCDIY QUICK LINK online
この上の各ジャンル名をクリックすると、下のウィンドウが切り替わります▼


=リンク集のインデックスはこちら=

資料書籍

About

2004年05月11日 13:18に投稿されたエントリーのページです。

ひとつ前の投稿は「WindowsへTELNETログインするまでをバッチ処理で自動化したい」です。

次の投稿は「[NT系]回数を確認しながらコマンドを実行し、成功したらループから抜ける処理」です。

他にも多くのエントリーがあります。メインページアーカイブページも見てください。

This site is powered by Six Apart
Movable Type 3.33-ja
このブログについて | 運営:有限会社メディアポート