web-dev-qa-db-ja.com

Windowsバッチファイル:forループの変数の設定

同じ命名スキームのファイルがいくつかあります。サンプルとして、4つのファイルは「num_001_001.txt」、「num_002_001.txt」、「num_002_002.txt」、「num_002_003.txt」と呼ばれます

番号の最初のセットはそれがどの「パッケージ」であるかを表し、番号の2番目のセットは単にそれらを互いに区別するために使用されます。したがって、この例では、パッケージ001に1つのファイルがあり、パッケージ002に3つのファイルがあります。

Windows Vistaのバッチコマンドを作成して、すべてのファイルを取得し、それぞれのディレクトリが異なるパッケージを表す独自のディレクトリに移動します。したがって、パッケージ001のすべてのファイルをディレクトリ「001」に、002のすべてのファイルをディレクトリ「002」に移動したい

すべてのtxtファイルを反復処理してエコーするスクリプトを正常に作成しました。また、あるファイルを別の場所に移動するスクリプトを作成し、ディレクトリが存在しない場合は作成します。

ここで、部分文字列を使用する必要があると考えたため、%var:〜start、end%構文を使用してそれらを取得しました。テストとして、実際にサブストリングを抽出し、条件付きでディレクトリを作成できることを確認するためにこれを書きました

 @ echo off 
 set temp = num_001_001.txt 
存在しない場合%temp:〜0,7%\ 
 mkdir%temp:〜0,7% 

そしてそれは動作します。すごい。
それから、forループを追加しました。

@echo off 
 FOR/R %% X IN(* .txt)DO(
 set temp = %%〜nX 
 echo directory%temp:〜0,7%
)

しかし、これは私の出力です:

ディレクトリnum_002 
ディレクトリnum_002 
ディレクトリnum_002 
ディレクトリnum_002 

どうしましたか? Vistaは、各反復での変数の再割り当てをサポートしていませんか? 4つのファイルは私のディレクトリにあり、そのうちの1つはnum_001を作成します。 003 004 005の異なるファイルを入力しましたが、それはすべて最後のパッケージの名前でした。私が物事をどのように設定しているかで何かが間違っていると推測しています。

私は仕事を終わらせるためにさまざまな回避策を持っていますが、なぜそのような単純な概念がうまくいかないのか困惑しています。

25

問題は、バッチプロセッサがforコマンドを実行する前に読み取ると、変数が置き換えられることです。

これを試して:

SET temp=Hello, world!
CALL yourbatchfile.bat

Helloが5回印刷されます。

解決策は遅延拡張です。最初に有効にしてから、!temp!の代わりに%temp%を使用する必要があります。

@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /R %%X IN (*.txt) DO (
  set temp=%%~nX
  echo directory !temp:~0,7!
)

詳細については、 here を参照してください。

54
configurator

別の解決策は、forループの本体をサブルーチンに移動し、call itにすることです。

@echo off
FOR /R %%X IN (*.txt) DO call :body %%X
goto :eof

:body
set temp=%~n1
echo directory %temp:~0,7%
goto :eof

どうしてですか? 1つの理由は、Windowsコマンドプロセッサがかっこについて貪欲であり、結果が驚くかもしれないことです。通常、C:\Program Files (x86)を含む変数を逆参照するときにこれに遭遇します。

Windowsコマンドプロセッサの貪欲度が低い場合、次のコードはOne (1)Two (2)を出力するか、まったく出力しません。

@echo off
if "%1" == "yes" (
   echo 1 (One)
   echo 2 (Two)
)

しかし、それはそうではありません。 1 (One2 (Two)を出力しますが、)が欠落しているか、2 (Two)を出力します。コマンドプロセッサは、Oneの後の)ifステートメントのボディの終わりとして解釈し、2番目のechoifステートメントの外側にあるものとして扱い、最後の)を無視します。

14
bk1e

これが公式に文書化されているかどうかはわかりませんが、callステートメントを使用して遅延展開をシミュレートできます。

@echo off
FOR /R %%X IN (*.txt) DO (
  set temp=%%~nX
  call echo directory %%temp:~0,7%%
)

パーセント記号を2倍にすると、変数の置換は2番目の評価まで延期されます。ただし、遅延拡張ははるかに簡単です。

4
bk1e