Форум программистов, компьютерный форум, киберфорум
Наши страницы

Batch (CMD/BAT)

Войти
Регистрация
Восстановить пароль
 
 
Dragokas
Эксперт WindowsАвтор FAQ
16242 / 6941 / 834
Регистрация: 25.12.2011
Сообщений: 10,722
Записей в блоге: 16
#1

Циклические операции и примеры (команда FOR) * [Статья] - CMD/BAT

04.02.2013, 00:56. Просмотров 86261. Ответов 16
Метки нет (Все метки)

Вдохновившись сообщением от FraidZZ, написал мини-статейку, основанную на изложенных ним положениях.

Заметки
Циклическиe операции FOR

Командой FOR задаётся список команд, которые выполняются с КАЖДЫМ элементом набора.
Набор* пишется внутри IN (...)
Список команд пишется внутри DO (...)
Командная строка выполняет эти команды раз за разом, при этом текущий элемент набора находится в переменной, заданной после %% (назовём ее переменной цикла).

Например,
Bash
1
FOR %%a IN (C:\Users\*.txt) DO echo %%a
выведет имена и путь ко всем файлам с расширением .txt в папке C:\Users.

* Примеры под спойлером
Виды наборов для FOR

Для команды For без ключей набором может являться:

1) Маска файлов* (или путь + маска файлов)
- в двойных кавычках, или без них:

IN (*.txt)
Результат: список файлов с расширением .txt в текущем каталоге.

IN (*.txt *.bat)
Результат: список файлов с расширениеми .txt и .bat в текущем каталоге.

IN ("C:\Folder 1\Doc_31-12-*.txt")
Результат: тот же. Но поиск ведется в каталоге C:\Folder 1 (заметьте с пробелом в имени);
имя файла начинается на Doc_31-12-

Прим.: FOR без ключа не умеет выводить список каталогов.
* маска файлов - это набор файлов, заданный с помощью подстановочных знаков * и/или ?
где * - обозначает 0 или больше любых символов в имени файла.
а ? - означает 0 или 1 любой символ в имени файла.

2) Строка
- в двойных кавычках, или без них:

Строкой считается любая последовательность символов, если она не содержит знаков маски * или ?
Смысл цикла здесь в том, чтобы разбить такую строку по пробелам (или знакам табуляции)
и выполнить с каждой подстрокой список команд.

Bash
1
FOR %%a IN (гитара рыбка) do echo Моя %%a
Результат:
Моя гитара
Моя рыбка
Если мы хотим, чтобы какая-то из строк не "билась" по пробелам, укажем ее в двойных кавычках:
Bash
1
FOR %%a IN (гитара "дорогая рыбка") do echo Моя %%~a
Результат:
Моя гитара
Моя дорогая рыбка
При этом, чтобы не выводились сами кавычки "" мы используем модификатор* ~ (тильда) при раскрытии переменной цикла %%~a

*О других модификаторах переменной цикла можно почитать здесь и здесь.

Не по теме:

3) еще есть смешанный тип. Это когда в наборе стоит маска (1-й описанный тип), а через пробел Строка (2 тип)... ведет себя вполне ожидаемо, но вряд ли найдет себе применение.



О наборах для FOR с ключем /F далее в нижнем спойлере.


Ключ /F часто используется для построчного разбора файла, т.е.
Bash
1
FOR /f "usebackq delims=" %%a IN ("C:\1.txt") DO echo %%a
выведет все строки файла 1.txt, который находится в корне диска C.

UseBackQ (Use back quotes) означает, что набор с двойными кавычками* подразумевает передачу в цикл имени файла.
delims= означает, что в переменную %%a будет записана вся строка (без разделения по пробелу или знаку табуляции, т.к. стандартный разделитель заменен на NULL (пустой символ).
В такой вариации:
tokens=* приводит к тому же результату, что и delims=. Означает прекратить разбивку по разделителю после "0-го" токена, т.е. сразу же.

* Этот вариант необходим для работы с файлом, путь или имя которого содержит пробелы.
Можно было не использовать UseBackQ, тогда команда приняла бы вид:
Bash
1
FOR /f "tokens=" %%a IN (C:\1.txt) DO echo %%a
но такая конструкция восприняла бы пробел в имени как определение нового файла, поэтому UseBackQ более приемлем.

** Примеры под спойлером
Виды наборов для FOR /F

В цикле FOR /F вид задаваемого набора зависит от формы кавычек в IN (...), а также наличия ключевого слова UseBackQ

Виды наборов для FOR /F:
1) Набор файлов (задание маски недопустимо!)

без UseBackQ - задается без кавычек IN (...)
__с UseBackQ - может задаваться как в кавычках так и без них. IN (...) IN ("...")

Специфика работы

Функционал: чтение содержимого файла(ов) построчно в переменную цикла!

Принцип работы: источником для разбиения по разделителю (delims) является содержимое файла, заданного внутри IN (...) или файлов, если они заданы через пробел.

Исключение: принятый по-умолчанию разделитель (пробел и знак табуляции) для этой конструкции цикла не применяется.

А что получится, если установить delims= (возле равно - знак пробела) ?
Bash
1
FOR /F "delims= " %%a in (1.txt) do echo %%a
В выводе на экран командой Echo %%a мы получим содержимое файла, где каждая из строк будет напечатана до первого встретившегося пробела.
.


2) Строка (допускаются практически любые символы)

без UseBackQ - задается с двойными кавычками IN ("...")
__с UseBackQ - задается с одиночными прямыми кавычками IN ('...')

3) Команда (сначала выполняется она, а уже ее результаты обрабатываются циклом как строка(-и))

без UseBackQ - задается с одиночными прямыми кавычками IN ('...')
__с UseBackQ - задается с одиночными обратными кавычками IN (`...`)

Примеры:

1.1. Чтение файла - Набор файлов
Bash
1
FOR /F %%a IN (c:\users\1.txt c:\users\2.txt) do echo.%%a
Результат: выведет подряд содержимое двух файлов - 1.txt и 2.txt из каталога c:\users
Прим.: Echo. - с точкой - это обход ошибки, чтобы можно было напечатать пустую строку, точнее строку с пробелами.

1.2. Чтение файла - Набор файлов + UseBackQ
Получаем возможность использовать пробелы.
Bash
1
FOR /F "usebackq" %%a IN ("c:\folder 1\1.txt") do echo.%%a
Результат: выведет содержимое файла 1.txt из каталога c:\folder 1
(заметьте, в имени папки есть пробел).


2.1. Строка
Bash
1
FOR /F %%a in ("Каждое слово в отдельную переменную") DO echo a=%%a; b=%%b; c=%%c; d=%%d; e=%%e
Цитата Сообщение от Результат
a=Каждое; b=слово; c=в; d=отдельную; e=переменную
2.2. Строка + UseBackQ
Bash
1
FOR /F "UseBackQ" %%a in ('Каждое слово в отдельную переменную') DO echo a=%%a; b=%%b; c=%%c; d=%%d; e=%%e
Результат такой же.

3.1. Команда
Bash
1
For /F "tokens=1-4" %%a IN ('Dir /A:D-L') Do Echo Папка %%d Дата модификации %%a. Время %%b
Сначала выполняется Dir /AD-L, которая выводит информацию о папках в текущем каталоге.
Вот что попадает под разбор циклу:



Далее цикл разбирает каждую строку по пробелам и табуляции на подстроки (токены).
На примере 1-й строки:
1-й токен (%%a)=29.12.2012 ...2-й токен (%%b)=15:16 ...3-й токен (%%c)=<DIR> ...4-й токен (%%d)=Favorites
...
Результат через Echo выводится на экран:
Папка Favorites Дата модификации 29.12.2012. Время 15:16
Папка Links Дата модификации 14.01.2013. Время 01:51
...и т.д.
3.2. Команда + UseBackQ
Bash
1
For /F "Usebackq tokens=1-4" %%a IN (`Dir /A:D-L`) Do Echo Папка %%d Дата модификации %%a. Время %%b
Результат такой же.
Альтернативный вариант нужен с целью, если одна из выполняемых команд требует точно такие же кавычки как и ключевое слово IN (...).
Дабы не пользоваться символом экранирования, просто применяем другие кавычки.


Отличительной особенностью FOR /F является умение работать через токены*,
а также поддержка дополнительных ключевых слов:
1) eol - знак комментария в начале строки (1-й символ). Т.е. строки с таким символом не будут обрабатываться. (по умолчанию, знак точки с запятой ; )
2) skip - пропуск определенного кол-ва обрабатываемых строк от начала файла
3) delims - задать другой разделитель(-ли) (по умолчанию, пробел и знак табуляции)
4) tokens - количество получаемых токенов (подстрок) в теле цикла и пределы разбивки по разделителю.
Также можно задать конкретный № токена, который попадет в первую переменную цикла.
5) usebackq - изменение правил использования кавычек внутри IN (...)

Детальную справку можно получить, введя в консоль команду FOR /?

* Токены - это подстроки, которые попадают в переменные цикла %% в каждой из итераций.
Они получаются в результате разбивки строки, заданной в IN (...), по разделителю, заданному в Delims= (по умолчанию, пробел и знак табуляции).

В отличие, от FOR без ключа, в FOR /F все токены (все подстроки одной строки) попадают сразу В ПЕРВУЮ ИТЕРАЦИЮ цикла.
Они будут распределены по РАЗНЫМ переменным цикла, идущим в алфавитном порядке*, начиная с буквы, заданной после FOR /F %%

Т.е.
Bash
1
FOR /F "tokens=1,2" %%a IN ("гитара рыбка") do echo Моя %%a и моя %%b.
Результат:
Моя гитара и моя рыбка.
Обратите внимание: по умолчанию, цикл выдаёт в результатах только 1-ый токен. Если вам нужно, получить другой, нужно явно указывать модификатор "tokens=xxx".

*
Макс. количество токенов и обход ограничения

Максимальное кол-во токенов составляет - 26,
если начальным указать %%a либо %%A (регистр имеет значение)
При этом переход с %%z в %%A не происходит. Остальная часть подстрок опускается.
Можно проверить:
Bash
For /F "tokens=1,2" %%z IN ("1 2") do echo %%A
Бывают случаи, когда требуется разбить строку по специфическому разделителю и при этом выполнить одну и ту же команду над каждой из подстрок (токеном). Кол-во токенов неизвестно.
Метод показал Anonymоus в теме Символ переноса строки в переменной окружения

Алгоритм заключается в замене разделителя на пробел с одновременным заключением каждого токена в двойные кавычки. Далее строка разбирается обычным циклом FOR без ключа.


Более универсальные конструкции на основе FOR /F для работы с файлами/папками строятся путем помещения
в IN ('...') команды, результаты от выполнения которой уж затем обрабатываются циклом.
Чаще всего это команда Dir.

А теперь рассмотрим более сложный пример:


1.2. Чтение файла (сложный пример).
Давайте возьмем сложный пример, и раскусим "крепкий орешек"
Bash
1
FOR /F "UseBackQ skip=1 tokens=2 delims=/\ eol=" %%X in ("%~dp01.txt") do echo %%X
Имеем в распоряжении файл 1.txt, который находится рядом с батником.
Цитата Сообщение от Содержимое файла 1.txt
первая строка
;комментарий/кода
наше любимое\блюдо
Порядок разбора (или "как прибл. будет думать ком. строка"):
1) %~dp0 - означает каталог, где находится батник, например c:\temp\

2) UseBackQ, ага - значит если в IN (...) ничего нет или двойные кавычки, то это файл и его нужно прочесть.

3) Читаем содержимое файла 1.txt в папке %~dp0, а затем каждую его строку проверяем по правилам... ключевых слов skip=1 tokens=2 delims=/\ eol=

4) Итак, первая строка так и называется "первая строка"
skip=1 - означает пропустить от начала файла 1-у строку,
значит идем дальше:

5) Вторая строка: ";комментарий/кода"
Первый символ - это точка с запятой. А теперь смотрим сюда "eol=пустой символ".
По умолчанию eol=; и если бы мы не указали пустой EOL, то цикл просто бы пропустил эту строку.
Итак, символ комментария не совпадает с заданным (т.е. он вообще пустой), а значит строчка нам подходит -> проверяем ее дальше:

6) Смотрим какие приняты разделители: delims=/\ (знаки / и \ ), значит
из строки ";комментарий/кода"
мы получим 2 подстроки:
1-й токен - ";комментарий"
2-й токен - "кода"

7) Теперь смотрим сюда tokens=2 - значит, что первой букве цикла нужно присвоить значение 2-го токена.
Первая буква цикла у нас X. Переменная называется %%X
А второй токен - это подстрока "кода"

8) Только теперь мы попадаем в тело цикла: Echo %%X
что означает - вывести на экран текст "кода"

С 3-ей строкой потренируйтесь самостоятельно.
Вот такой результат окажется на экране:

кода
блюдо



Ключ /L
Bash
1
FOR /L %%a IN (0,2,6) DO echo %%a
IN (первое, шаг, последнее)
означает математическое перечисление чисел от первого числа (0), до третьего (6), с шагом, указанным вторым числом (2) в наборе IN (...).

Указанная команда выведет:
0
2
4
6
Прим.: дробные числа командной строкой не поддерживаются.
11
Миниатюры
Циклические операции и примеры (команда FOR) * [Статья]  
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
04.02.2013, 00:56
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Циклические операции и примеры (команда FOR) * [Статья] (CMD/BAT):

Циклические операции. Программа не выдает ни результата, ни ошибки - VB
простенькая задача вроде исходник правильный а вывод с ошибкой то есть, ошибки не какой не выводит, да и вообще не какого результата не...

Добрый день. Вероятность того что команда а и команда б забьет 2,3,4,5 голов - Теория вероятностей
Команда а, сыграла дома 12 матчей забила 17 мячей и пропустила 7 Команда б, сыграла в гостях 12 матчей забила 11 мячей и пропустила 16 ...

Статья - Механика
Здравствуйте люди добрые, помогите пожалуйста, найти следующий статьи очень нужно. Я.Б.Зельдович, Д.А.Франк-Каменецкий, ЖФХ, 12, 100...

Почему команда «dir>test.txt» работает, а команда «ftp /?>test.txt» — нет? - CMD/BAT
Пробовала без пробелов, что тут еще можно попробовать непонятно Выводит в окно командной строки. Как исправить?

Статья о Томкат - Java
слышали? оказывается томкат - не полосатый, а пятнистый. и этакий зверь грозный :)) http://www.oreilly.com/catalog/tomcat/

Случайная статья - PHP БД
Здравствуйте, я только начал работать с php и хотел бы узнать код случайного вывода статей, тут нарисовал в паинте но что-то сам не знаю...

16
Dragokas
Эксперт WindowsАвтор FAQ
16242 / 6941 / 834
Регистрация: 25.12.2011
Сообщений: 10,722
Записей в блоге: 16
04.02.2016, 21:54  [ТС] #16
mostApi, позволю себе перефразировать:

Присвоение переменной результата выполнения внешнего исполняемого файла.
Windows Batch file
1
for /f "delims=" %%a in ('file.exe') do set "var=%%a"
Добавлено через 1 минуту
Это если результат выполнения - 1 строка.
1
semiono
12 / 12 / 0
Регистрация: 14.09.2010
Сообщений: 282
Записей в блоге: 6
30.04.2017, 23:56 #17
FOR %%a IN (C:\$\*.sfp) do dd if=C:\$\patch of="%%a" bs=1d

Я надеюсь без ошибок будет?
Вроде получилось патчить файлы утилитой dd for windows!
0
30.04.2017, 23:56
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
30.04.2017, 23:56
Привет! Вот еще темы с ответами:

Статья на конференцию - Turbo Pascal
Здравствуйте! Не могу найти актуальную тему для статьи на &quot;научную&quot; конференцию, подкиньте идеи?

Статья о комментариях - PHP
Здравствуйте . Читал статью о том как сделать комментарии для сайта и не понял что должно быть на месте Вмонтируйтеидвашейстатьи : ...

Не открывается статья - Joomla
Всем привет. Нужна помощь. Я создал сайт в программе Artisteer для движка Joomala, точнее не сайт а просто шаблон. Установил движок Joomala...

Вводная статья - Lisp
Нужна основательная вводная статья(книги, которые удалось найти достаточно большие, если у вас на примете есть что-то до 100...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Закрытая тема Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru