23

私は20年間数十の言語でプログラミングを行ってきましたが、どんなに頑張っても、Windowsのcmdシェルバッチファイルで「FOR」がどのように機能するかを理解できませんでした。私は読む

http://www.amazon.com/Windows-Administration-Command-Line-Vista/dp/0470046163/ref=sr_1_1?ie=UTF8&s=books&qid=1241362727&sr=8-1

http://www.ss64.com/nt/for.html

およびインターネット上の他のいくつかの記事ですが、それでも混乱し、何も達成できません。

「FOR」が一般的にどのように機能するかについて、誰かが私に簡潔な説明をすることができますか?

もう少し具体的な質問については、%PATH%変数の各パスを反復処理するにはどうすればよいですか?私はで試しました

rem showpathenv.bat
for /f "delims=;" %%g in ("%PATH%") do echo %%g

すべてではなく、最初のパスのみが表示されます。なんで ?私が間違っていることは何ですか?

4

12 に答える 12

12

実際に機能する答えはありません。私は自分で解決策を見つけることができました。これは少しハックですが、私にとっては問題を解決します:

echo off
setlocal enableextensions
setlocal enabledelayedexpansion
set MAX_TRIES=100
set P=%PATH%
for /L %%a in (1, 1, %MAX_TRIES%) do (
  for /F "delims=;" %%g in ("!P!") do (
    echo %%g
    set P=!P:%%g;=!
    if "!P!" == "%%g" goto :eof
  )
)

おー !私はバッチファイルプログラミングが嫌いです!!

更新しました

マークの解決策はより単純ですが、空白を含むパスでは機能しません。これは、マークのソリューションを少し変更したバージョンです

echo off
setlocal enabledelayedexpansion
set NonBlankPath=%PATH: =#%
set TabbedPath=%NonBlankPath:;= %
for %%g in (%TabbedPath%) do (
  set GG=%%g
  echo !GG:#= !
)
于 2009-05-04T02:22:07.810 に答える
5

マークのアイデアは良かったのですが、パスにスペースがあるのを忘れたのかもしれません。';'を置き換える 代わりに'""'を使用すると、すべてのパスが引用符で囲まれた文字列にカットされます。

set _path="%PATH:;=" "%"
for %%p in (%_path%) do if not "%%~p"=="" echo %%~p

ここに、パスが表示されます。

cmdのFORコマンドには、特に()のステートメント内で変数がどのように反応するかという理由で、面倒な学習曲線があります...任意の変数を割り当てることができますが、「 setlocal ENABLEDELAYEDEXPANSION "ステートメント。したがって、%%の(!_var!)の代わりに!!の変数も使用します。

私は現在、cmdを使用してスクリプトを作成していますが、仕事のために、これをすべて学ぶ必要がありました:)

于 2009-08-18T12:58:36.230 に答える
4

あなたは正しい考えを持っていますがfor /f、個々の文字列ではなく、複数行のファイルまたはコマンドで動作するように設計されています。

最も単純な形式でforは、Perlforや他のすべての言語の に似ていforeachます。トークンのリストを渡すと、毎回同じコマンドを呼び出して反復処理します。

for %a in (hello world) do @echo %a

拡張機能は、トークンのリストを自動的に構築する方法を提供するだけです。現在のコードが何も表示されない理由は、' ;' がデフォルトの行末 (コメント) 記号であるためです。ただし、それを変更したとしても%%g, %%h, %%i, ...、個々のトークンにアクセスするために使用する必要があり、バッチ ファイルが大幅に制限されます。

あなたが求めるものに最も近いものは次のとおりです。

set TabbedPath=%PATH:;= %
for %%g in (%TabbedPath%) do echo %%g

ただし、セミコロンを含む引用符で囲まれたパスでは失敗します。

私の経験では、for /lfor /rは既存のコマンドを拡張するのに適していますが、それ以外forは非常に制限されています。遅延変数展開 ( ) を使用すると、もう少し強力 (かつ混乱を招く) にすることができますがcmd /v:on、実際にはファイル名のリストにのみ適しています。

文字列操作を実行する必要がある場合は、WSH または PowerShell を使用することをお勧めします。whereisWindows 用に作成しようとしている場合は、 を試してくださいwhere /?

于 2009-05-03T15:28:57.460 に答える
4

このスレッドが古いので、これを投げ出すことに抵抗できませんでした...通常、PATHの各ファイルを反復処理する必要が生じた場合、本当にやりたいことは特定のファイルを見つけることだけです...その場合、このワンライナーは、ファイルを見つけた最初のディレクトリを吐き出します:

(例: java.exe を探す)

for %%x in (java.exe) do echo %%~dp$PATH:x
于 2013-02-24T17:48:34.403 に答える
3

私はこれが非常に古いことを知っています...しかし、ただの楽しみのために、これを試してみることにしました:

@Echo OFF
setlocal
set testpath=%path: =#%
FOR /F "tokens=* delims=;" %%P in ("%testpath%") do call :loop %%P
:loop
if '%1'=='' goto endloop
set testpath=%1
set testpath=%testpath:#= %
echo %testpath%
SHIFT
goto :loop
:endloop
pause
endlocal
exit

これはカウントを必要とせず、終了するまで続きます。スペースでも同じ問題がありましたが、変数全体を通過しました。これの鍵は、ループ ラベルとSHIFT関数です。

于 2012-05-01T16:13:35.780 に答える
2

これは私のために働きます:

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION ENABLEEXTENSIONS
@REM insure path is terminated with a ;
set tpath=%path%;
echo.
:again
@REM This FOR statement grabs the first element in the path
FOR /F "delims=;" %%I IN ("%TPATH%") DO (
  echo    %%I 
  @REM remove the current element of the path
  set TPATH=!TPATH:%%I;=!
)
@REM loop back if there is more to do. 
IF DEFINED TPATH GOTO :again

ENDLOCAL
于 2009-09-15T19:34:04.957 に答える
2

for /f行入力ごとに反復するため、プログラムでは最初のパスのみを出力します。

プログラムは %PATH% を 1 行の入力として扱い、 で区切り;、最初の結果を %%g に置き、%%g (最初に区切られたパス) を出力します。

于 2009-05-03T15:23:11.560 に答える
2

FOR基本的に、データセット内の「行」を反復しています。この場合、パスを含む行が 1 行あります。"delims=;"セミコロンで区切るように指示しているだけです。body を に変更するecho %%g,%%h,%%i,%%j,%%kと、入力が 1 行として扱われ、複数のトークンに分割されていることがわかります。

于 2009-05-03T15:31:20.450 に答える
2

ループが許可するtokens=1,2,...オプションの一部を追加で使用する必要があります。forこれは、おそらくあなたが望むことを行います:

for /f "tokens=1,2,3,4,5,6,7,8,9,10,11,12 delims=;" %a in ("%PATH%") ^
do ( ^
     echo. %b ^
   & echo. %a ^
   & echo. %c ^
   & echo. %d ^
   & echo. %e ^
   & echo. %f ^
   & echo. %g ^
   & echo. %h ^
   & echo. %i ^
   & echo. %j ^
   & echo. %k ^
   & echo. ^
   & echo.   ...and now for some more... ^
   & echo. ^
   & echo. %a ^| %b ___ %c ... %d ^
   & dir "%e" ^
   & cd "%f" ^
   & dir /tw "%g" ^
   & echo. "%h  %i  %j  %k" ^
   & cacls "%f")

この例では、最初の 12 個のトークン (= %path% からのディレクトリ) のみを処理します。使用される各トークンの明示的な列挙を使用します。トークン名は大文字と小文字が区別されることに注意してください。%a は %A とは異なります。

スペースを含むパスを保存するには、すべての%x をこの "%i" のように引用符で囲みます。ここでは、トークンをエコーするだけなので、それはしませんでした。

s.th を行うこともできます。このような:

for /f "tokens=1,3,5,7-26* delims=;" %a in ("%PATH%") ^
do ( ^
     echo. %c ^
   & echo. %b ^
   & echo. %a ^
   & echo. %d ^
   & echo. %e ^
   & echo. %f ^
   & echo. %g ^
   & echo. %h ^
   & echo. %i ^
   & echo. %j ^
   & echo. %k )

これはトークン 2、4、6 をスキップし、小さなショートカット (" 7-26") を使用して残りのトークンに名前を付けます。今回は %c、%b、%a が逆の順序で処理され、最初の例と比較して異なるトークンを「意味する」ことに注意してください。

したがって、これは確かにあなたが求めた簡潔な説明ではありません。しかし、おそらく例はもう少し明確にするのに役立つでしょう...

于 2010-08-07T22:09:05.420 に答える
1

ここに良いガイドがあります:

FOR /F - ループ コマンド: 一連のファイルに対して。

FOR /F - コマンドのループ: 別のコマンドの結果に対して。

FOR - ループ コマンド: すべてのオプション ファイル、ディレクトリ、リスト。

[ガイド全体 (Windows XP コマンド):

http://www.ss64.com/nt/index.html

編集:申し訳ありませんが、Amazonリンクの一部として私には見えたので、リンクがすでにOPにあることを知りませんでした.

于 2009-05-03T15:39:56.170 に答える
0

それは私のために働く、試してみてください。

for /f "delims=;" %g in ('echo %PATH%') do echo %g%
于 2015-09-11T14:16:44.653 に答える