Подтвердить что ты не робот

Как работает "FOR" в командном файле cmd?

Я программировал на десятках языков в течение 20 лет, но я никогда не мог понять, как "FOR" работает в пакетном файле командной строки cmd, независимо от того, насколько сильно я пытался. Я прочитал

http://www.amazon.com/Windows-Administration-Command-Line-Vista/dp/0470046163/ref=sr_1_1?ie=UTF8& S = книги & QID = 1241362727 & ср = 8-1

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

и несколько других статей в Интернете, но все еще запутывают и ничего не могут сделать.

Может ли кто-нибудь дать мне краткое объяснение того, как работает "FOR"?

Для более конкретного вопроса, как я могу перебирать каждый путь в переменной% PATH%? Я пробовал с помощью

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

Это будет показывать только первый путь, не все из них. Зачем? Что я делаю неправильно?

4b9b3361

Ответ 1

Ни один из ответов не работает. Мне удалось найти решение самостоятельно. Это немного хакерский, но он решает проблему для меня:

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
  )
)

О! Я ненавижу программирование пакетных файлов!

Обновление

Решение Mark проще, но оно не будет работать с пробелом, содержащим пробелы. Это модифицированная версия решения Mark

echo off
setlocal enabledelayedexpansion
set NonBlankPath=%PATH: =#%
set TabbedPath=%NonBlankPath:;= %
for %%g in (%TabbedPath%) do (
  set GG=%%g
  echo !GG:#= !
)

Ответ 2

Идея Mark была хороша, но, возможно, забыл, что в ней есть пробелы. Замена ';' с '' "'вместо этого вырезал бы все пути в строки с кавычками.

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

Итак, здесь отображаются ваши пути.

Команда

FOR в cmd имеет утомительную кривую обучения, особенно потому, что как переменные реагируют внутри() операторов... вы можете назначить любые переменные, но вы не можете прочитать их обратно в(), если вы не используете "setlocal ENABLEDELAYEDEXPANSION", и поэтому также используйте переменные с!! вместо %% (! _var!)

Я в настоящее время исключительно script с cmd, для работы, должен был изучить все это:)

Ответ 3

У вас есть правильная идея, но for /f предназначен для работы с многострочными файлами или командами, а не с отдельными строками.

В своей простейшей форме for похож на Perl for или на любой другой язык foreach. Вы передаете ему список токенов, и он выполняет итерацию по ним, вызывая одну и ту же команду каждый раз.

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

Расширения просто предоставляют автоматические способы построения списка токенов. Причина, по которой ваш текущий код ничего не приносит, заключается в том, что ";" является символом конца строки (комментария) по умолчанию. Но даже если вы измените это, вам придется использовать %%g, %%h, %%i, ... для доступа к отдельным токенам, что сильно ограничит ваш пакетный файл.

Ближе всего вы можете дойти до того, что вы просите:

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

Но это не сработает для цитируемых путей, содержащих точки с запятой.

По моему опыту, for /l и for /r хороши для расширения существующих команд, но в противном случае for крайне ограничен. Вы можете сделать его несколько более мощным (и запутанным) с замедленным расширением переменной (cmd /v:on), но это действительно полезно только для списков имен файлов.

Я бы предложил использовать WSH или PowerShell, если вам нужно выполнить строковые манипуляции. Если вы пытаетесь написать whereis для Windows, попробуйте where /?.

Ответ 4

Не удалось удержаться от этого, старый, поскольку этот поток... Обычно, когда возникает необходимость перебирать каждый из файлов в PATH, все, что вы действительно хотите сделать, это найти конкретный файл... Если что случай, этот однострочный слой выплюнет первый каталог, в котором он найдет ваш файл:

(например: поиск java.exe)

for %%x in (java.exe) do echo %%~dp$PATH:x

Ответ 5

Я знаю, что это СУПЕР старый... но просто для удовольствия я решил попробовать:

@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.

Ответ 6

for /f итерации на каждый ввод строки, поэтому в вашей программе будет выводиться только первый путь.

ваша программа рассматривает% PATH% как однострочный ввод и делимирует на ;, ставит первый результат на %% g, а затем выводит %% g (первый разграниченный путь).

Ответ 7

FOR по существу выполняет итерацию по "линиям" в наборе данных. В этом случае есть одна строка, содержащая путь. "delims=;" просто говорит, что он отделяется на полуколонах. Если вы измените тело на echo %%g,%%h,%%i,%%j,%%k, вы увидите, что он обрабатывает ввод как одну строку и разбивает его на несколько токенов.

Ответ 8

Это работает для меня:

@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

Ответ 9

Вот хорошее руководство:

FOR/F - команда Loop: против набора файлов.

FOR/F - команда Loop: против результатов другой команды.

Команда FOR - Loop: все параметры Файлы, каталог, список.

[Все руководство (команды Windows XP):

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

Изменить: Извините, не видел, что ссылка уже была в OP, как мне показалось, как часть ссылки Amazon.

Ответ 10

Вы должны дополнительно использовать часть 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". Я не делал этого здесь, где я только вторгаюсь в токены.

Вы также можете сделать это. например:

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 обрабатываются в обратном порядке на этот раз и как они теперь "означают" разные токены по сравнению с первым примером.

Так что это, конечно, не краткое объяснение, которое вы просили. Но, может быть, примеры помогут прояснить ситуацию немного лучше...

Ответ 11

Это работает для меня, попробуйте.

for /f "delims=;" %g in ('echo %PATH%') do echo %g%

Ответ 12

Это работает для меня, попробуйте.

для/f "tokens = * delims =;" % g in ('echo% PATH%') делают эхо% g%