1

現在、アイテムのリストを実行してディレクトリ (アーカイブ) にコピーするループがあります。ただし、リスト内の項目の 1 つ (パス名にグローバル変数を含む) が「文字通り」(コードではなくテキストとして) 解釈されています。通常、(^^) を介して行をエスケープして、テキストではなくコードとして解釈できることはわかっていますが、機能していないため、明らかにここで何か間違ったことをしています...

問題が発生している my.list (エスケープを含む) の項目は次のとおりです。

location\foo^^%date:~0,3%*.zip

私が使用しているコードは...

for /f "delims=" %%a in (my.list) do (
    echo "%%a"
)

エコーズ

"location\foo^^%date:~0,3%*.zip"

それ以外の

location\fooMON*.zip

どんな助けでも大歓迎です。

4

1 に答える 1

5

文字をいつエスケープする必要があるかについて混乱しています。

一部の文字には特別な意味があります (「コード」と説明します)。多くの場合、「コード」ではなくリテラル (テキスト) として解釈されるように文字をエスケープできます。

Windows CMD.EXE 内で文字をエスケープする最も一般的な方法は、先頭に 1^文字を付けることです。文字列が 2 回解析される場合があり、これには , のエスケープ シーケンスが必要になる場合があります^^^(または、遅延展開が有効になっている場合^^に対処する場合)。!解析のラウンドが増えると、さらに多くの^文字が必要になります。すぐに混乱する可能性があり、コツをつかむには練習が必要です。

しかし、あなたの状況はまったく異なります - 逃げることによって解決することはできません。FOR変数内に「コード」があり、それをそのように解釈したいとします。しかし代わりに、それはテキストとして解釈されています。その理由を理解するには、バッチ解析のさまざまな段階が発生する順序を理解する必要があります。Windows コマンド インタープリター (CMD.EXE) はスクリプトをどのように解析しますか?を参照できます。、しかし、それは消化するのに時間がかかるかなり高度なものです.

これは、さまざまなタイプの拡張がいつ発生するかを示す大まかな概要です。(注 - これらのステップ番号は、リンクされた回答のフェーズ番号と正確には一致しません)

1) パラメータ展開 - %1
2) 通常の変数展開 - %var%
3) FOR 変数展開 - %%A
4) 遅延変数展開 - !var!
5) CALL 展開 - CALL が含まれる場合は、手順 1) と 2) を繰り返します

%date:~0,3%文字列を通常の (パーセント) 拡張する必要があります。FOR ループは、テキスト行を展開せずに逐語的に読み取ります。パーサーが最初に「コード」を確認するのは、ステップ 3) で%%aFOR 変数が展開されたときです。%date:~0,3%思い通りに拡張するには、これはすでに手遅れであることがわかり ます。

問題を解決するには、2 つの選択肢があります。ただし、注意してください。これらのソリューションはそれぞれ、解決が必要な新しい問題を追加する可能性があります。

埋め込ま^^れた「コード」の展開を強制するあなたの素朴な試みだと思います。をリスト ファイルから削除する必要があります^^

オプション 1: CALL を使用して通常の展開のラウンドを追加する

for /f "delims=" %%a in (my.list) do call echo "%%a"

しかし、ここでは、展開したくない%リテラルがリストに含まれている可能性があるという潜在的な問題があります。バッチ スクリプト内のパーセントは、 でエスケープできません。代わりに、パーセントを 2 倍にしてエスケープします。したがって、リストにパーセント リテラルがある場合は、それらを 2 倍にする必要があります。^%%

質問とともに投稿された元のコードは、はるかに複雑であることに注意してください。を参照する IF ステートメントが含まれていました%%a。IF または FOR コマンドを呼び出すことはできません。解決策は、サブルーチンを呼び出して値を渡し、サブルーチンに複雑なロジックを含めることです。

for /f "delims=" %%a in (my.list) do call :processValue "%%a" >>Logs\xfer.log
exit /b

:processValue
echo Attempting to archive %1...
if exist "c:\%~1" (
  echo f | xcopy "c:\%%a" "c:\Lucas\archive\%~1" /E /C /H /R /Y
  if %errorlevel%==0 (
    echo ...%1 added to archive for transfer
    echo.
  ) else (
    echo ERROR: %1 not added to archive
    echo.
  )
) else (
  echo ERROR: %1 Not found on client computer
  echo.
)

オプション 2: 遅延展開を使用する

遅延展開を有効にし、リストを!date:~0,3!の代わりに使用するように変更します%date:~0,3%。FOR変数の展開後に遅延展開が発生するため、正常に展開されます。

setlocal enableDelayedExpansion
for /f "delims=" %%a in (my.list) do echo "%%a"

しかし、ここでは、展開したくない!リテラルがリストに含まれている可能性があるという潜在的な問題があります。としてエスケープすることで、リテラルを保持できます。!^!

于 2013-10-30T14:46:20.460 に答える