Вопрос

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

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

и несколько других статей в Интернете, но все равно сбивает с толку и ничего не может сделать.

Может ли кто-нибудь дать мне краткое объяснение того, как вообще работает «ЗА»?

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

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

Это покажет только первый путь, а не все.Почему ?Что я делаю не так?

Это было полезно?

Решение

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

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:#= !
)

Другие советы

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

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

Итак, у вас есть ваши пути, отображаемые.

Команда

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

Мне в настоящее время исключительно сценарий с cmd, для работы, пришлось изучить все это:)

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

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

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

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

Самое близкое, к чему вы можете обратиться -

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

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

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

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

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

(например: ищу java.exe)

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

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

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

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

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

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

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

@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

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

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

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

FOR / F - команда цикла: для набора файлов.

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top