Windows bat файлы for

Команда FOR задает запуск некоторой команды для каждого файла из заданного множества.

Работу команды for можно охарактеризовать так:

a) получение диапазона данных
b) присвоить переменной цикла for (например %%G) значение из диапазона данных
c) выполнить команду (иногда в команде участвует %%G, например, в качестве параметра)
d) выполнить шаги a), b), c), пока не будет достигнуто конечное значение из диапазона значений переменной цикла.

Очень хорошо команда for описана в справке w2k.

Синтаксис

for {% | %%}< переменная > in (< множество >) do < команда > [< ПараметрыКоманднойСтроки > ]

Параметры команды for следующие:

Параметр Описание
{%% | %}< переменная > Обязательный элемент, который представляет замещаемое значение. Используйте один знак %, чтобы выполнить команду for из командной строки (не в командном файле). Два знака %% используются для команды for, выполняемой в составе командного файла (*.bat или *.cmd). Имена переменных чувствительны к регистру символов, и должны быть составлены из символов букв алфавита (например %a, %b или %c).
(< множество >) Обязательный элемент, указывает на один или несколько файлов, каталогов или текстовых строк, или диапазон значений, по которому должна проходить итерация команды for. Наличие круглых скобок обязательно.
< команда > Обязательный элемент, который указывает команду, выполняемого для каждого элемента множества (см. предыдущий параметр).
ПараметрыКоманднойСтроки Задает параметры командной строки, необходимые для использования с указанной командой (см. предыдущий параметр).
/? Отображение справки в командной строке для команды for.

Команду for можно использовать в командном файле (*.bat, *.cmd) или непосредственно запускать в командной строке.

Атрибуты. К команде for применяются перечисленные ниже атрибуты.

• В команде for переменная %переменная (или %%переменная) будет заменяться текстовой строкой из заданного параметра множество, пока параметр команда не обработает все файлы этого множества.
• Имена параметров переменная команды for учитывают регистр буквы, они являются глобальными, и одновременно может быть активно не больше 52 переменных.
• Для обозначения параметра переменная можно использовать любые знаки, кроме цифр 0–9, чтобы не было конфликта с параметрами пакетных файлов %0–%9. Для простых пакетных файлов вполне достаточно обозначений с одним знаком, например %%f.
• В сложных командных файлах могут быть использованы и другие обозначения для параметра переменная.

Задание множества файлов. Параметр множество может представлять группу файлов или несколько групп файлов. Для задания групп файлов можно использовать подстановочные знаки (* и ?). Следующие множества файлов являются допустимыми:

(*.doc)
(*.doc *.txt *.me)
(jan*.doc jan*.rpt feb*.doc feb*.rpt)
(ar??1991.* ap??1991.*)

Когда используется команда for, первое значение в параметре множество заменяет параметр %переменная (или %%переменная), а затем для обработки этого значения выполняется указанная команда. Это продолжается до тех пор, пока не будут обработаны все файлы (или группы файлов), которые соответствуют значению параметра множество.

in и do. Ключевые слова in и do не являются параметрами, но они требуются для работы команды for. Если какое-то из этих слов пропущено, на экран будет выведено сообщение об ошибке.

Использование дополнительных форм команды for. Если расширения командного процессора разрешены (по умолчанию), то поддерживаются следующие дополнительные формы команды for.

• Только каталоги

Если параметр множество содержит подстановочные знаки (* и ?), команда, указанная в параметре команда, выполняется для каждого каталога (кроме множества файлов в указанном каталоге), совпадающего с параметром множество. Используется следующий синтаксис.
for /D {%% | %}переменная in (множество) do команда [ПараметрыКоманднойСтроки]

• Рекурсивная

Проходит по дереву каталогов с корнем в [диск:]путь, выполняя инструкцию for для каждого каталога в дереве. Если после ключа /R не задан каталог, предполагается текущий каталог. Если параметр множество задан одной точкой (.), то команда просто перечислит каталоги в дереве. Используется следующий синтаксис.
for /R [[диск:]путь] {%% | %}переменная in (множество) do команда [ПараметрыКоманднойСтроки]

• Итерация диапазона значений

Используйте переменную итерации для установки начального значения (НачальноеЗначение#), а затем перемещайтесь по диапазону значений, пока значение не превысит конечное значение множества (КонечноеЗначение#). /L выполнит итерацию, сравнив параметр НачальноеЗначение# с параметром КонечноеЗначение#. Если параметрНачальноеЗначение# меньше параметра КонечноеЗначение#, то выполняется команда. Когда переменная итерации превысит параметр КонечноеЗначение#, командная оболочка покидает цикл. Также можно использовать отрицательный параметр шаг# для перемещения в диапазоне убывающих значений. Например, (1,1,5) создает последовательность «1 2 3 4 5», а (5,-1,1) создает последовательность «5 4 3 2 1». Используется следующий синтаксис.
for /L {%% | %}переменная in (НачальноеЗначение#,шаг#,КонечноеЗначение#) do команда [ПараметрыКоманднойСтроки]

• Итерация и разбор файлов

Разбор файлов следует использовать для обработки вывода команды, строк и содержимого файла. Используйте переменные итерации для определения содержимого или строк, которые требуется проверить. Параметр КлючевыеСловаРазбора используется для изменения разбора. Используйте параметр маркера КлючевыеСловаРазбора для указания маркеров, которые воспринимаются как переменные итерации. Примечание. Без параметра маркера ключ /F проверяет только первый маркер.

Разбор файлов состоит в чтении вывода, строки или содержимого файла, разбиении его на отдельные строки текста и разборе каждой строки на ноль или маркеры. Цикл программы for затем вызывается с переменной итерации, установленной в маркер. По умолчанию /F передает первый отделенный пробелом элемент из каждой строки каждого файла. Пустые строки пропускаются. Используется также другой синтаксис.
for /F [«КлючевыеСловаРазбора»] {%% | %}переменная lin (МножествоИменФайлов) do команда [ПараметрыКоманднойСтроки]
for /F [«КлючевыеСловаРазбора»] {%% | %}переменная in («СимвольнаяСтрока») do команда [ПараметрыКоманднойСтроки]
for /F [«КлючевыеСловаРазбора»] {%% | %}переменная in (‘команда’) do команда [ПараметрыКоманднойСтроки]

Аргумент МножествоИменФайлов задает одно или несколько имен файлов. Каждый файл открывается, считывается и обрабатывается до перехода к следующему файлу параметра МножествоИменФайлов. Чтобы переопределить стандартное поведение разбора, укажите параметр «КлючевыеСловаРазбора». Это строка, заключенная в кавычки, которая содержит одно или несколько ключевых слов для указания различных режимов разбора.

Если используется параметр usebackq, используйте один из приведенных ниже синтаксисов:
for /F [«usebackqКлючевыеСловаРазбора»] {%% | %}переменная in («МножествоИменФайлов») do команда [ПараметрыКоманднойСтроки]
for /F [«usebackqКлючевыеСловаРазбора»] {%% | %}переменная in (‘СимвольнаяСтрока’) do команда [ПараметрыКоманднойСтроки]
for /F [«usebackqКлючевыеСловаРазбора»] {%% | %}переменная in (‘команда’) do команда [ПараметрыКоманднойСтроки]

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

Ключевое слово Описание
eol=c Задает символ конца строки (только один символ).
skip=N Задает число строк, пропускаемых в начале файла.
delims=xxx Задает набор разделителей. Заменяет набор разделителей по умолчанию, состоящий из пробела и символа табуляции.
tokens=X,Y,M-N Задает элементы, передаваемые из каждой строки в тело цикла for при каждой итерации. В результате размещаются дополнительные имена переменных. Форма M-N задает диапазон, указывающий элементы с M-го по N-ый. Если последним символом строки tokens= является звездочка (*), то размещается дополнительная переменная, в которую помещается остаток строки после разбора последнего элемента.
usebackq Задает возможность использования кавычек для имен файлов в параметре МножествоИменФайлов. Задает исполнение строки, заключенной в обратные кавычки, как команды, а строки в одиночных кавычках — как команды в символьной строке.

• Подстановка переменных

Были расширены модификаторы подстановок для ссылок на переменные в for. Приведенная ниже таблица перечисляет варианты синтаксических конструкций (на примере переменной I).

Переменная с модификатором Описание
%~I Расширение %I, которое удаляет окружающие кавычки («»).
%~fI Расширение %I до полного имени пути.
%~dI Замена %I именем диска.
%~pI Замена %I на путь.
%~nI Замена %I одним именем файла.
%~xI Замена %I расширением имени файла.
%~sI Замена путем, содержащим только короткие имена.
%~aI Замена %I атрибутами файла.
%~tI

Замена %I временем модификации файла.

%~zI Замена %I размером файла.
%~$PATH:I Поиск в каталогах, перечисленных в переменной среды PATH, и замена %I полным именем первого найденного файла. Если переменная среды не определена или поиск не обнаружил файлов, модификатор выдает пустую строку.

Приведенная ниже таблица перечисляет комбинации модификаторов, которые можно использовать для получения более сложных результатов.

Переменная с объединенными модификаторами Описание
%~dpI Замена %I именем диска и путем.
%~nxI Замена %I именем файла и расширением.
%~fsI Замена %I полным именем пути с короткими именами.
%~dp$PATH:I Поиск в каталогах, перечисленных в переменной среды PATH, и замена %I именем диска и путем первого найденного файла.
%~ftzaI Замена %I строкой, аналогичной результату работы команды dir.

В приведенных выше примерах %I и PATH могут быть заменены другими допустимыми значениями. Допустимое имя переменной for прекращает синтаксис %~.

Использование прописных букв в именах переменных, например %I, может улучшить восприятие программы и позволит избежать недоразумений с модификаторами, в которых строчные и прописные буквы не различаются.

Разбор строки. Конструкция for /F может быть использована непосредственно для строки. Для этого поместите параметр МножествоИменФайлов между скобками в одиночные кавычки (‘МножествоИменФайлов’). Параметр МножествоИменФайлов будет воспринят как одиночная строка ввода из файла и будет разобран.

Разбор вывода. Команду for /F можно использовать для разбора вывода команды. Для этого поместите параметр МножествоИменФайлов между скобками в обратные кавычки. Он будет воспринят как командная строка, которая передается дочернему интерпретатору командной строки Cmd.exe, а результаты работы команды помещаются в памяти и разбираются, как если бы они являлись файлом.

[Примеры]

В пакетных файлах используется следующий синтаксис для команды for:
for %%переменная in (множество) do команда [ПараметрыКоманднойСтроки]

Чтобы отобразить содержимое всех файлов, имеющих разрешение DOC или TXT, в текущем каталоге с помощью заменяемой переменной %f, введите следующую команду:
for %%f in (*.doc *.txt) do type %%f

В предыдущем примере каждый файл с расширением .doc или .txt в текущем каталоге будет подставляться вместо переменной %f, пока не будет выведено содержимое всех файлов. Для использования этой команды в пакетном файле нужно заменить каждую команду %f на %%а. В противном случае переменная игнорируется и выводится сообщение об ошибке.

Чтобы произвести разбор файла, игнорируя комментарии, можно использовать следующую команду:
for /F «eol=; tokens=2,3* delims=,» %i in (myfile.txt) do @echo %i %j %k

Данная команда производит разбор каждой строки в файле Myfile.txt, игнорируя строки, начинающиеся с точки с запятой, и передает второй и третий элементы из каждой строки в тело цикла команды FOR. Элементы разделяются запятыми или пробелами. Тело инструкции FOR использует %i для получения второго элемента, %j для получения третьего элемента и %k для получения оставшихся элементов в строке. Если имена файлов содержат пробелы, их следует заключать в кавычки (например, «ИмяФайла»). Для использования кавычек необходима команда usebackq. В противном случае кавычки рассматриваются как определение символьной строки для разбора.

Переменная %i объявлена явно в инструкции FOR. Переменные %j и %k объявлены явно при использовании tokens=. С помощью tokens= можно указать до 26 элементов, если это не вызовет попытки объявить переменную с именем, большим буквы «z» или «Z».

Для разбора вывода команды с помощью помещения параметра МножествоИменФайлов в скобки можно использовать следующую команду (пример выводит список имен всех переменных окружения):
for /F «usebackq delims==» %i IN (`set`) DO @echo %i

Ищем в директориях файлы с расширением html содержащие строку google:
for /R %%f in (*.html) do @findstr /m «google» %%f

FOR /L
выполнить команду для диапазона чисел
Синтаксис
FOR /L %%parameter IN (start,step,end) DO command

Где
   start      первое число (включительно)
   step       инкремент числа для каждого шага
   end        последнее число (включительно)
   command    выполняемая команда, здесь же указываются параметры командной строки для неё
   %%parameter изменяемый при каждой прокрутке цикла параметр (переменная цикла)

Внутри командного файла в качестве параметра используйте %%G, а в командной строке %G (такие уж Микрософт придумал правила). (20,-5,10) будет генерить последовательность 20 15 10, а (1,1,5) последовательность 1 2 3 4 5.

Пример
FOR /L %%G IN (1,1,5) DO echo %%G

Можно использовать нечисловой список, например:
FOR %%G IN (Sun Mon Tue Wed Thur Fri Sat) DO echo %%G

[Другие команды for]

FOR — цикл по всем файлам в одной директории (исключая её подкаталоги)
FOR /R — цикл по всем файлам, включая подкаталоги
FOR /D — цикл через несколько папок
FOR /F — цикл через слова в текстовом файле или через вывод команды

syntax-FOR-Files
     FOR %%parameter IN (set) DO command
syntax-FOR-Files-Rooted at Path
     FOR /R [[drive:]path] %%parameter IN (set) DO command
syntax-FOR-Folders
     FOR /D %%parameter IN (folder_set) DO command
syntax-FOR-List of numbers
     FOR /L %%parameter IN (start,step,end) DO command
syntax-FOR-File contents
     FOR /F [«options»] %%parameter IN (filenameset) DO command
     FOR /F [«options»] %%parameter IN («Text string to process») DO command
syntax-FOR-Command Results
     FOR /F [«options»] %%parameter IN (‘command to process’) DO command

[Связанные с for команды]

FORFILES (w2003 Server) — выборка списка файлов из директории для отображения или использования при обработке в bat-файле
GOTO метка — прямой переход на строку в командном файле, помеченную строкой :метка
IF — условное выполнение команды

[Equivalent Linux BASH commands]

for — Expand words, and execute commands
case — Conditionally perform a command
eval — Evaluate several commands/arguments
if — Conditionally perform a command
gawk — Find and Replace text within file(s)
m4 — Macro processor
until — Execute commands (until error)
while — Execute commands

[Условные обозначения форматирования]

Формат Описание
Курсив Сведения, вводимые пользователем
Полужирный шрифт Элементы, вводимые без изменений
Многоточие (…) Параметр может быть введен в командной строке несколько раз
В квадратных скобках ([]) Необязательные элементы
В фигурных скобках ({}), варианты, разделенные вертикальной линией (|). Пример: {even|odd} Набор вариантов, из которых необходимо выбрать один
Courier font Программа или выходные данные

[Ссылки]

1. Практические приемы программирования в bat-файлах.

Бат-файлы ведут свою историю со времен MS-DOS. Новые фичи добавлялись с сохранением обратной совместимости. Из-за этого многое в языке bat-файлов, как мы увидим далее, нелогично и неудобно.

Вместе с тем, в bat-файле можно использовать переменные, условия, циклы и подпрограммы. При помощи некоторых костылей можно передавать данные на вход команд и разбирать их вывод. Проще говоря, можно программировать.

В этой статье мы постараемся дать обзор основных элементов языка командного интерпретатора Windows, с помощью которых можно реализовать любой алгоритм.

Зачем же сегодня использовать этот язык? Главным образом, для автоматизации выполнения консольных команд. Запуск команд выполняется в bat-файле проще, чем в каком-либо другом языке: инструкция запуска команды – это сама команда без каких бы то ни было ключевых слов, знаков препинания и подключаемых библиотек.

Для сравнения, Java, .NET и Python для выполнения этой простой задачи требуют подключить библиотеку/сборку/модуль и вызвать метод.

Язык C++ сам по себе вообще не определяет для этого стандартный и независимый от платформы способ. Тут вам понадобится библиотека целевой операционной системы. В Windows это windows.h и функция CreateProcess(), а в Linux надо вызвать fork(), а затем exec().

Второе место по простоте вызова команд операционной системы занимает Perl – в нем достаточно заключить команду в обратные кавычки (``).

Первое место с bat-файлами делят PowerShell и bash.

Зачем же разбирать командный интерпретатор, а не Power Shell, который, кроме всего прочего, дает доступ ко всему богатству возможностей .NET Framework?

Прежде всего, ради искусства. Разные люди делают интересные вещи чисто на bat-файлах именно потому, что это сложно. Т.е. можно рассматривать язык командного интерпретатора как эзотерический язык программирования.

Кроме того, как-то раз в реальном проекте мне пришлось поддерживать bat-скрипты. Так что рано их списывать со счетов как морально устаревшую технологию.

Еще одно полезное отличительное свойство командного интерпретатора – для получения справки не нужен ни Гугл, ни интернет. Нужно лишь набрать команду help. Причем, информация русском языке, если у вас русская винда.

Переменные

Переменные в bat-файлах – это переменные окружения. Это значит, что все переменные, установленные скриптом, доступны процессам, которые он запускает. Это надо иметь ввиду при работе с паролями.

Переменные создаются и изменяются командой set:

set hello=world

Создали переменную с именем hello и значением world.

Команда set без параметров выводит список всех переменных.

Следующая строка выведет слово «world»:

echo %hello%

Имена переменных нечувствительны к регистру. Следующая строка тоже выведет слово «world»:

echo %HELLO%

Значения переменных могут содержать знак равенства:

set equation=x=y
echo %equation%

выведет x=y

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

Специальные переменные

Переменные, перечисленные ниже, используют один знак %, только в начале, в отличие от обычных переменных.

%0 – имя bat-файла, который сейчас выполняется, в том виде, как оно указано в командной строке. Для запуска bat-файла его имя может быть написано с полным путем, с относительным путем, без пути, с расширением, без расширения, маленькими или заглавными буквами. Соответственно, в переменной %0 оно может оказаться во всех этих вариантах. Но в любом случае командой %0 скрипт запускает сам себя.

%1, %2%9 – параметры. Командная строка разделяется на токены по пробелам. При этом каждая часть, заключенная в кавычки, считается одним токеном. Кавычки, если есть, тоже попадают в эти переменные.

%* – все параметры, т.е. всё, что идет в командной строке после имени bat-файла, со всеми кавычками и пробелами, какие есть.

%errorlevel% — код возврата последней команды

%CD% — текущая директория

%DATE% и %TIME% — текущие дата и время

%RANDOM% — случайное число

Преобразование параметров при подстановке

%~1 – первый параметр без кавычек. Как вы помните, параметр может быть указан либо в кавычках, либо без них, и кавычки, если они есть, будут и в переменной. От того, есть ли кавычки в переменной, зависит, будет ли содержащее ее выражение синтаксически правильным. Проверить наличие кавычек с помощью оператора if не получится, потому что в одном из двух случаев выполнение скрипта прервется из-за синтаксической ошибки. Однако, тильда перед именем переменной гарантирует, что кавычек на месте этой переменной не будет.

%~dp0 – полный путь к папке текущего bat-файла, без имени самого файла.

%~nx0 – имя и расширение текущего bat-файла, без пути

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

Цикл FOR

Это единственный вид цикла. Если нужно что-то типа while или until, то придется использовать операторы if и goto.

Зато цикл FOR имеет несколько опций, выходящих за рамки того, что обычно делает цикл

Итерирование по словам

Пример

@echo off
FOR %%a in (one two three) do echo %%a

Выводит каждое слово в новой строке:

one
two
three

@echo off отключает вывод команд. @ перед командой отключает вывод данной команды

Этот пример необходимо записать в bat-файл и запустить файл. Если вводить цикл в командной строке, то он должен выглядеть слегка иначе:

FOR %a in (one two three) do @echo %a

Да, синтаксис переменной цикла зависит от того, вводим ли мы этот цикл в командной строке или он записан в файл. Если какой-то софт запускает команду, которую вы ему укажете, и вы хотите использовать в ней цикл, синтаксис зависит от того, каким образом этот софт передает команду командному интерпретатору. Это можно делать через командную строку или через стандартный ввод. В этих случаях используется один знак процента. Вариант с файлом мы уже пробовали в примере. Там используются два знака процента.

Цикл разбирает строку в скобках по тем же правилам, что параметры командной строки: строка в кавычках – это один параметр. Пример:

@echo off
FOR %%a in ("twenty one" "twenty two") do echo %%~a

Выводит две строки:

twenty one
twenty two

Строки выводятся без кавычек, потому что использована переменная %%~a. %%a содержит кавычки.

Цикл по файлам или папкам

Следующая команда выводит список файлов в текущем каталоге:

FOR %%a in (*.*) do echo %%a

А так можно получить список папок:

FOR /D %%a in (*.*) do echo %%a

Параметр /R включает обход всех подкаталогов. При этом в переменной цикла полные пути:

FOR /R %%a in (*.*) do echo %%a

FOR /D /R %%a in (*.*) do echo %%a

Вместо «*.*» можно писать просто «*«. Результат абсолютно такой же: в обоих случаях выбираются файлы как с расширениями, так и без.

Цикл по числам с заданным шагом

Используем параметр /L, а в скобках указываем начало, шаг и конец (включительно) через запятую. Обратите внимание, что для числа, указанного как конец интервала, команда тоже будет вызвана, если длина интервала делится на шаг. Шаг может быть отрицательным.

FOR /L %%a in (10,-1,5) do @echo %%a

Выводит:

10
9
8
7
6
5

Разбор файлов и строк

FOR /F %%a in (список.txt список2.txt) do echo %%a

Каждый файл открывается, каждая строка читается и разбивается на одну или более подстрок. Подстроки записываются в отдельные переменные. Например, если переменная цикла — %%a, то будут созданы переменные %%a, %%b, %%c и т.д.

При разборе строки разделителями по умолчанию считаются пробелы и табуляции.

Вот так можно разобрать строку, указанную непосредственно:

FOR /F %%a in (“строка”) do echo %%a

А так разбирается вывод команды. Это вообще единственный способ получить вывод команды в переменную. То есть, даже если вывод состоит из одной строки, и ее не надо разбирать, всё равно приходится писать цикл.

FOR /F %%a (‘dir /B’) do echo %%a

Выводит список файлов, разбирая вывод команды dir.

Наберите help for, чтобы узнать все опции.

Вызов подпрограмм и других скриптов

Очередная контринтуитивная фича bat-файлов в том, что, если из одного bat-файла вызвать другой, выполнение первого файла не продолжится, если только не использовать ключевое слово call. То есть, мы должны разбираться, чем является команда, которую мы хотим вызвать. Если это bat-файл, то надо перед его именем написать call. Если это exe-файл или встроенная команда, то это слово не нужно. Кроме того, если вызываемый скрипт использует команду exit, то выполнение также не вернется к нам. Чтобы завершить только текущий скрипт, надо писать exit /B.

При вызове одного скрипта из другого не создается новый процесс. Поэтому переменные окружения, установленные вызванным скриптом, видны вызывающему.

В следующем примере a.bat вызывает b.bat. Этот пример также демонстрирует работу с кодом завершения процесса.

a.bat

@echo off
echo Before call
call b.bat
echo b.bat returned %errorlevel%

b.bat

echo Inside b.bat
exit /B 1

Выводит:

Before call
Inside b.bat
b.bat returned 1

Командой call также можно вызвать код, находящийся в том же файле:

@echo off
echo Before call
call :b
echo b returned %errorlevel%
goto :eof

:b
echo Inside b.bat
exit /B 1

Работает аналогично предыдущему примеру, но это один файл.

С двоеточия начинаются метки. На них можно переходить командами call и goto. В языке bat-файлов нет понятия подпрограммы. Мы будем так называть код, который вызывается через call и возвращает управление через exit /B или goto :eof. Метка :eof не определена, и это не ошибка. Эта метка не нуждается в определении. Она всегда означает конец файла. Т.е. переход на :eof – это выход – то же, что и exit /B, но без кода завершения.

Условия

if a==a echo 1

Выводит 1.

if a==b echo 1

Ничего не выводит.

Если строки до и после знаков равенства совпадают с учетом регистра, то команда выполняется, иначе не выполняется. В обеих строках можно использовать переменные. При этом надо иметь ввиду, что в переменных может быть всё, что угодно, включая знаки равенства и пустые строки. От значений переменных будет зависеть синтаксическая правильность команды.

Вот такой способ проверить параметр командной строки работает и при отсутствии параметра, и если в нем спецсимволы:

if "%~1"=="help" echo This is a test script && exit /B

Оператор && — это один из способов выполнить несколько команд под условием. На самом деле это ленивое «и», т.е. если первая команда вернет ненулевой errorlevel, то вторая уже не выполнится.

Другой способ – скобки:

if "%~1"=="help" (
 echo This is help
 exit /B
) else (
 Echo This is the main part
)

Как видите, со скобками можно использовать слово else.

Насчет скобок нужно помнить одну вещь. Условие или цикл с блоком команд в скобках – это одна команда. Значения переменных в ней подставляются один раз в самом начале.

То есть, нельзя внутри такого блока присвоить значение переменной и позже в том же блоке его использовать. Нельзя присвоить значение на одной итерации цикла и использовать на другой.

При таких сценариях приходится выносить код в подпрограммы.

Есть еще поздняя подстановка переменных. Ее надо включать командой SETLOCAL ENABLEDELAYEDEXPANSION, а вместо символа «%» использовать «!«.

Разыменование переменных

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

Допустим, переменная A содержит ключ:

set A=aaa

Записать значение по ключу можно так:

set %A%=bbb

Следующая команда выведет «bbb»:

echo %aaa%

А вот читать по ключу не так просто. Подстановка переменных не рекурсивна. То есть, нельзя, используя только знак «%», подставить «aaa» вместо «A», а затем, «bbb» вместо «aaa».

Тут нам поможет поздняя подстановка. Она тоже не рекурсивна. Однако, используя сразу оба вида подстановок, можно выполнить замену в два этапа:

SETLOCAL ENABLEDELAYEDEXPANSION
echo !%A%!

Выводит «bbb».

Желающие усложнить себе задачу отказом от поздней подстановки, могут разбирать вывод команды set при помощи цикла for:

for /F "tokens=1,2 delims==" %%a in ('set %A%') do if "%%a"=="%A%" echo %%b

Обратите внимание, что в цикле надо проверять имя переменной, которую нам вернули, даже если указать имя нужной переменной в команде set. Дело в том, что могут существовать переменные с именами, начинающимися с нужного. Если убрать параметр команды set, результат не изменится. Но указывая этот параметр, мы оптимизируем алгоритм. Но это не точно.

Арифметика

Команда set /A вычисляет выражения

SET /A A=2+3
ECHO %A%

Выводит 5

Замена подстрок

SET A=abcdefgh
ECHO %A:c=C%

Заменяет строчную букву C на заглавную. Выводит:

abCdefgh

Выбор подстроки:

ECHO %A:~4,2%

Выводит 2 символа, начиная с 5-го, в данном случае «ef«.

Ввод пользователя

SET /P A=Enter something:

Выведет приглашение для ввода и будет ждать ввода строки. Введенная строка окажется в переменной A.

Заключение

Язык командного интерпретатора имеет многолетнюю историю и дожил до наших дней. Он доступен на чистой винде и удобен для автоматизации выполнения команд. При этом он является языком программирования, и позволяет реализовать алгоритмы любой сложности. Самое главное в таком деле – найти подходящие инструменты командной строки, дающие доступ к нужным возможностям. Вместе с тем решение задач на bat-файлах с использованием ограниченного набора внешних команд может быть интересным упражнением.

1. Overview of loops in Batch language

  • Space

  • Comma ( , )

  • Semi-colon ( ; )

  • TAB

2. For Loop (Default)

For loop (default) of Batch language is used to iterate over a list of files.

Syntax:

@rem set_of_files -  Set of Files
@rem Files separated by standard delimiters.
@rem The parameter name 'variable' must be 1 character
FOR %%variable IN ( set_of_files ) DO command

@rem Hoặc:
FOR %%parameter IN ( set_of_files ) DO  (
     command
)

Example: copy some files into a directory (Note: the files to be copied into the target directory need to be in the same disk drive).

copyFiles.bat

@echo off
@rem Copy to same Disk

FOR %%f IN (E:\test\file1.data  E:\test\file2.txt) DO  (
   echo Copying %%f
   copy  %%f E:\backup
)
pause

Other example:

@rem The delimiter is a semicolon (;)
FOR %%f IN ("E:\my dir\file1.data" ; E:\test\file2.txt) DO copy %%f E:\backup

@rem The delimiter is a comma ( , )
FOR %%f IN ("E:\my dir\file1.data" , E:\test\file2.txt) DO copy %%f E:\backup

@rem The delimiter is a space.
FOR %%f IN ("E:\my dir\file1.data" E:\test\file2.txt) DO copy %%f E:\backup

3. For /R

The FOR /R loop is used to iterate over the list of files, including files in subdirectories, grandchildren .. It is called Recurse loop.

Syntax:

FOR /R [path] %%variable IN ( set_of_file_filters ) DO command

@rem Or:
FOR /R [path] %%variable IN ( set_of_file_filters ) DO (
   command
)
  • [path] : This parameter is a root folder. If there is not this parameter «the folder containing executable script file» hoặc «current folder» will be considered as root folder .

  • set_of_file_filters : List of file filters, for example *.txt , *.bat, … or dot ( . ) means all.

  • variable: means name of variable and must have one unique characte.

The following example prints the list of all *.txt or *.log files in the C:/Windows/System32 directory (Includes search in subdirectories, grandchildren ..)

forR_example1.bat

@echo off
FOR /R "C:\Windows\System32" %%f IN (*.txt *.log) DO  (
   echo %%f
)
pause

Example of listing all files in the C:/Windows/System32 directory (including files in subdirectories, grandchildren …)

forR_example2.bat

@echo off 
FOR /R "C:\Windows\System32" %%f IN ( . ) DO  ( 
   echo %%f
)
pause

4. For /D

The FOR /D loop is used to iterate over the list of directories which are subdirectories of current directory.

Syntax:

FOR /D [/r] %%variable IN ( set_of_directory_filters ) DO command

@rem Or:
FOR /D [/r] %%parameter IN ( set_of_directory_filters ) DO  (
    command
)
  • set_of_directory_filters : List of directory filters for example, en*, fr*,.. separated by a standard delimiter.

  • [/r]: This is a recurse parameter and not mandatory. If this parameter is available, subdirectories, grandchildren .. will be envolved in the loop.

  • variable: means name of variable and must have a unique character.

Example: List subdirectories of C:/Windows.

forD_example1.bat

@echo off
C:
cd C:/Windows

FOR /D %%d IN ( * ) DO  (
   echo %%d
)
pause

Example: List subdirectories, grandchildren … of the C:/Windows with the name started by «en» or «fr»

forD_example2.bat

@echo off
C:
cd C:/Windows

FOR /D /r %%d IN (en* fr*) DO  (
   echo %%d
)
pause

5. For /L

For /L loop is used to iterate over a range of numbers.

Syntax:

FOR /L %%variable IN (start, step, end) DO command

@rem Or:
FOR /L %%variable IN (start, step, end) DO  (
     command
)
  • start: The first value of variable

  • step: After each iteration, variable value will be added ‘step’.

  • end: Last value.

Example:

forL_example1.bat

@echo off 
FOR /L %%d IN (1 2 8 ) DO  (
   echo %%d
)
pause

forL_example2.bat

@echo off 
FOR /L %%d IN (20 -2 5 ) DO  (
   echo %%d
)
pause

6. For /F

The For /F loop is a complex but powerful loop. It reads a file or a few files and then analyzes the contents of files. The content of a file is a text; it is split into several small pieces of text, each of which is called a Token. The default rule for separating a text is based on white space. However, you can customize the delimiter rule by [«delims = xxx»] parameter.

The For / F loop is also used to analyze the contents of a string, or to execute a set of commands.

Syntax:

FOR /F ["options"] %%variable IN ( set_of_filenames ) DO command

FOR /F ["options"] %%variable IN ( set_of_filenames ) DO (
     command
)
FOR /F ["options"] %%variable IN ("Text string to process") DO command
FOR /F ["options"] %%variable IN ("Text string to process") DO ( 
     command
)
  • set_of_filenames: List of a or several files.

  • options: Options, for example, «delims=, tokens=1,2,4»

Option

Description

delims=xxx

Delimiter character(s). by default is a space

skip=n

The first line number will be ignored in the contents of file, defaulted skip = 0

eol=;

eol (End of Line): Specifies a special character, which is put at the beginning of a line to mark this line as comment line. Comment lines will be ignored by the program, defaulted semicolon character (;)

tokens=n1,n2,n3

defines the positions cared about (n1, n2, n3, ..), defaulted tokens=1

usebackq

(See explanation in examples)

To be easy to understand, let’s analyze the following file:

eol (End of Line)

eol: Used to specify a special character, which is by default a semicolon character (;). It is placed at the beginning of a line to mark that such line is a comment. The program will ignore this line.

skip=n

skip: Declare the number of first lines of the file will be ignored, the program will not analyze these lines. Default skip = 0

delims (Delimiter character(s))

delims: Defines delimiter characters, helping the program to delimit each line of text into sub-paragraphs, each of which is called a Token. Tokens are marked indices: 1, 2, 3, …

tokens=n1,n2,n3

tokens: Declare a list of indices that are interested in, separated by commas. For example, tokens = 1,2,4, defaulted: tokens = 1

The indices such as 1, 2, 4 are interested.

The indices of 2 to 8 are interested

The indices such as 3, 4,5, … are interested

All indices are interested

For example, «tokens=1,2,4», means that Tokens at the position of 1, 2, 4 are interested and other Tokens will be ignored.

Example of file analysis:

Example of using the FOR /F loop to read persons.txt file:

persons.txt

List of celebrities
Creation date: 2017/09/11

; (Comment) Male List
Bill,Gates,1955/10/28,Male
Steve,Jobs,1955/02/24,Male
Mark,Zuckerberg,1984/05/16,Male
Sundar,Pichai,1972/07/12,Male
; (Comment) Female List
Hillary,Clinton,1947/10/26,Female

forF_example1.bat

@echo off 
FOR /F "delims=, skip=3 eol=; tokens=1,2,4" %%i IN ( persons.txt ) DO  (
   echo Full Name: %%i %%j   Gender: %%k
)
pause

Note: Name of variables on the loop has only character .

Biến %%i variable is explicitly declared on the loop. %% j, %% k variables are implicitly declared (names of implicit variables are the next characters of explicit variable names).

Example of String analysis:

  • TODO

1.
%A vs. %%A

 
%A is for use on command lines only.
In all examples and syntax lines shown %A should be substituted with %%A when used in batch files.

2.
%a vs. %A

 
The A in %A may be replaced by any character, either upper case or lower case, except numbers.
Note, however, that variables are case sensitive, so be consistent:
FOR %A IN (1 2 3) DO ECHO %a
will not work.
FOR %? IN (1 2 3) DO ECHO %?
on the other hand, will.

3.
Nesting FOR commands

 
In DOS (COMMAND.COM), nesting FOR commands is not possible.
However, by using a second command processor you may still be able to nest them:
FOR %A IN (1 2 3) DO COMMAND /C FOR %B IN (A B C) DO ECHO %A%B
Note that you cannot replace COMMAND /C with CALL

In NT (CMD.EXE) nesting is possible.
Note that to nest FOR loops, each loop requires its own variable; i.e.
FOR %A IN (1 2) DO FOR %A IN (A B) DO ECHO %A
will lead to undesired results:
A
B
A
B

FOR %A IN (1 2) DO FOR %B IN (A B) DO ECHO %A%B
will work as planned, and display:
1A
1B
2A
2B

4.
Commands in list

 
list may not only contain a list of parameters, it may even contain a list of commands that can be executed consecutively with the same parameters. i.e. command may also be %A:
DIR > tempfile.txt
FOR %A IN (TYPE DEL) DO %A tempfile.txt

This FOR loop will first type the temporary file and then delete it.

5.
list delimiters

 
The «elements» in list can be delimited (separated) by spaces, tabs, commas or semicolons.
As of MS-DOS 7, doublequoted strings are treated as a single element, whether they contain delimiters or not.

In NT, it is possible to define your own delimiters with FOR /F.

6.
Forward slashes in list

 
If list starts with a forward slash, COMMAND.COM (except MS-DOS 7) will split the string in list into its first character following the forward slash and the remainder of the string.
This is demonstrated in the interactive FOR examples

7.
Conditional manipulation of variables in command

 
The following does not work:
FOR %%A IN (1 2 3) DO IF "%VAR%"=="" SET VAR=%%A
sets VAR to 3, not 1
The %VAR% in the comparison (IF «%VAR%»==»») is interpreted immediately, and thus empty, and then the FOR loop is started.
From the FOR loop’s point of view, the command issued was:
FOR %%A IN (1 2 3) DO IF ""=="" SET VAR=%%A
The following construction can be used as a workaround:
FOR %%A IN (1 2 3) DO CALL TEST2.BAT %%A
If TEST2.BAT looks like this:
IF "%VAR%"=="" SET VAR=%1
then VAR is set to 1
In NT either delayed variable expansion or a CALL to a subroutine could be used instead.

8.
Jump using GOTO in command

 
FOR %%A IN (1 2 3) DO GOTO=%%A
:1
ECHO 1
GOTO End
:2
ECHO 2
GOTO End
:3
ECHO 3
:End

will display different results for different command interpreters:

  • CMD.EXE (NT and OS/2) will jump to label 1
  • COMMAND.COM (DOS) will jump to label 1, then 2, then 3,
    without executing any of the following commands, and then
    execute the ECHO 3 and following commands

Цикл FOR /R … IN … DO …

С помощью ключа /R можно задать рекурсию в команде: FOR:

FOR /R [[диск:]путь] %%переменная IN (набор) 
  DO команда [параметры]

В этом случае заданная команда выполняется для каталога [диск:]путь, а также для всех подкаталогов этого пути. Если после ключа R не указано имя каталога, то выполнение команды начинается с текущего каталога. Например, для распечатки всех файлов с расширением txt в текущем каталоге и всех его подкаталогах можно использовать следующий пакетный файл:

@ECHO OFF
CLS
FOR /R %%f IN (*.txt) DO PRINT %%f

Если вместо набора указана только точка (.), то команда проверяет все подкаталоги текущего каталога. Например, если мы находимся в каталоге C:\TEXT с двумя подкаталогами BOOKS и ARTICLES, то в результате выполнения файла:

@ECHO OFF
CLS
FOR /R %%f IN (.) DO ECHO %%f
на экран выведутся три строки:
C:\TEXT\.
C:\TEXT\BOOKS\.
C:\TEXT\ARTICLES\.
Цикл FOR /L … IN … DO …

Ключ /L позволяет реализовать с помощью команды FOR арифметический цикл, в этом случае синтаксис имеет следующий: вид:

FOR /L %%переменная IN (начало,шаг,конец) DO команда [параметры]

Здесь заданная после ключевого слова IN тройка (начало,шаг,конец) раскрывается в последовательность чисел с заданными началом, концом и шагом приращения. Так, набор (1,1,5) раскрывается в (1 2 3 4 5), а набор (5,-1,1) заменяется на (5 4 3 2 1). Например, в результате выполнения следующего командного файла:

@ECHO OFF
CLS
FOR /L %%f IN (1,1,5) DO ECHO %%f

переменная цикла %%f пробежит значения от 1 до 5, и на экране напечатаются пять чисел:

Числа, получаемые в результате выполнения цикла FOR /L, можно использовать в арифметических вычислениях. Рассмотрим командный файл my.bat следующего содержания:

@ECHO OFF
CLS
FOR /L %%f IN (1,1,5) DO CALL :2 %%f
GOTO :EOF
:2
SET /A M=10*%1
ECHO 10*%1=%M%

В третьей строке в цикле происходит вызов нового контекста файла my.bat с текущим значением переменной цикла %%f в качестве параметра командной строки, причем управление передается на метку :2 (см. описание CALL в разделе «Изменения в командах перехода»). В шестой строке переменная цикла умножается на десять, и результат записывается в переменную M. Таким образом, в результате выполнения этого файла выведется следующая информация:

10*1=10
10*2=20
10*3=30
10*4=40
10*5=50
Цикл FOR /F … IN … DO …

Самые мощные возможности (и одновременно самый запутанный синтаксис) имеет команда: FOR с ключом /F:

FOR /F ["ключи"] %%переменная IN (набор) 
 DO команда [параметры]

Здесь параметр набор содержит имена одного или нескольких файлов, которые по очереди открываются, читаются и обрабатываются. Обработка состоит в чтении файла, разбиении его на отдельные строки текста и выделении из каждой строки заданного числа подстрок. Затем найденная подстрока используется в качестве значения переменной при выполнении основного тела цикла (заданной команды).

По умолчанию ключ /F выделяет из каждой строки файла первое слово, очищенное от окружающих его пробелов. Пустые строки в файле пропускаются. Необязательный параметр «ключи» служит для переопределения заданных по умолчанию правил обработки строк. Ключи представляют собой заключенную в кавычки строку, содержащую приведенные в табл. 3.3 ключевые слова:

Таблица
3.3.
Ключи в команде FOR /F

Ключ Описание
EOL=C Определение символа комментариев в начале строки (допускается задание только одного символа)
SKIP=N Число пропускаемых при обработке строк в начале файла
DELIMS=XXX Определение набора разделителей для замены заданных по умолчанию пробела и знака табуляции
TOKENS=X,Y,M-N Определение номеров подстрок, выделяемых из каждой строки файла и передаваемых для выполнения в тело цикла

При использовании ключа TOKENS=X,Y,M-N создаются дополнительные переменные. Формат M-N представляет собой диапазон подстрок с номерами от M до N. Если последний символ в строке TOKENS= является звездочкой, то создается дополнительная переменная, значением которой будет весь текст, оставшийся в строке после обработки последней подстроки.

Разберем применение этой команды на примере пакетного файла parser.bat, который производит разбор файла myfile.txt:

@ECHO OFF
IF NOT EXIST myfile.txt GOTO :NoFile
FOR /F "EOL=; TOKENS=2,3* DELIMS=, " %%i IN 
  (myfile.txt) DO @ECHO %%i %%j %%k
GOTO :EOF
:NoFile
ECHO Не найден файл myfile.txt!

Здесь во второй строке производится проверка наличия файла myfile.txt; в случае отсутствия этого файла выводится предупреждающее сообщение. Команда FOR в третьей строке обрабатывает файл myfile.txt следующим образом:

Пропускаются все строки, которые начинаются с символа точки с запятой ( EOL=; ).

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

В теле цикла переменная %%i используется для второй подстроки, %%j — для третьей, а %%k получает все оставшиеся подстроки после третьей.

В нашем примере переменная %%i явно описана в инструкции FOR, а переменные %%j и %%k описываются неявно с помощью ключа TOKENS=. Например, если в файле myfile.txt были записаны следующие три строки:

ААА ББББ ВВВВ,ГГГГГ ДДДД
ЕЕЕЕЕ,ЖЖЖЖ ЗЗЗЗ
;КККК ЛЛЛЛЛ МММММ

то в результате выполнения пакетного файла parser.bat на экран выведется следующее:

ББББ ВВВВ ГГГГГ ДДДД
ЖЖЖЖ ЗЗЗЗ

Замечание

Ключ TOKENS= позволяет извлечь из одной строки файла до 26 подстрок, поэтому запрещено использовать имена переменных, начинающиеся не с букв английского алфавита (a–z). Следует помнить, что имена переменных FOR являются глобальными, поэтому одновременно не может быть активно более 26 переменных.

Команда FOR /F также позволяет обработать отдельную строку. Для этого следует ввести нужную строку в кавычках вместо набора имен файлов в скобках. Строка будет обработана так, как будто она взята из файла. Например, файл следующего содержания:

@ECHO OFF
FOR /F "EOL=; TOKENS=2,3* DELIMS=, " %%i IN 
  ("ААА ББББ ВВВВ,ГГГГГ ДДДД") DO @ECHO %%i %%j %%k

при своем выполнении напечатает

Вместо явного задания строки для разбора можно пользоваться переменными среды, например:

@ECHO OFF
SET M=ААА ББББ ВВВВ,ГГГГГ ДДДД
FOR /F "EOL=; TOKENS=2,3* DELIMS=, 
  " %%i IN ("%M%") DO @ECHO %%i %%j %%k

Наконец, команда FOR /F позволяет обработать строку вывода другой команды. Для этого следует вместо набора имен файлов в скобках ввести строку вызова команды в апострофах (не в кавычках!). Строка передается для выполнения интерпретатору команд cmd.exe, а вывод этой команды записывается в память и обрабатывается так, как будто строка вывода взята из файла. Например, следующий командный файл:

@ECHO OFF
CLS
ECHO Имена переменных среды:
ECHO.
FOR /F "DELIMS==" %%i IN ('SET') DO ECHO %%i

выведет перечень имен всех переменных среды, определенных в настоящее время в системе.

В цикле FOR допускается применение тех же синтаксических конструкций (операторов), что и для заменяемых параметров (табл. 3.4).

Таблица
3.4.
Операторы для переменных команды FOR

Операторы Описание
%~Fi Переменная %i расширяется до полного имени файла
%~Di Из переменной %i выделяется только имя диска
%~Pi Из переменной %i выделяется только путь к файлу
%~Ni Из переменной %i выделяется только имя файла
%~Xi Из переменной %i выделяется расширение имени файла
%~Si Значение операторов N и X для переменной %i изменяется так, что они работают с кратким именем файла

Замечание

Если планируется использовать расширения подстановки значений в команде FOR, то следует внимательно подбирать имена переменных, чтобы они не пересекались с обозначениями формата.

Например, если мы находимся в каталоге C:\Program Files\Far и запустим командный файл следующего содержания:

@ECHO OFF
CLS
FOR %%i IN (*.txt) DO ECHO %%~Fi
то на экран выведутся полные имена всех файлов 
 с расширением txt:
C:\Program Files\Far\Contacts.txt
C:\Program Files\Far\FarFAQ.txt
C:\Program Files\Far\Far_Site.txt
C:\Program Files\Far\License.txt
C:\Program Files\Far\License.xUSSR.txt
C:\Program Files\Far\ReadMe.txt
C:\Program Files\Far\register.txt
C:\Program Files\Far\WhatsNew.txt
Циклы и связывание времени выполнения для переменных

Как и в рассмотренном выше примере с составными выражениями, при обработке переменных среды внутри цикла могут возникать труднообъяснимые ошибки, связанные с ранними связыванием переменных. Рассмотрим пример. Пусть имеется командный файл следующего содержания:

SET a=
FOR %%i IN (Раз,Два,Три) DO SET a=%a%%%i
ECHO a=%a%

В результате его выполнения на экран будет выведена строка «a=Три», то есть фактически команда

FOR %%i IN (Раз,Два,Три) DO SET a=%a%%%i

равносильна команде

FOR %%i IN (Раз,Два,Три) DO SET a=%%i

Для исправления ситуации нужно, как и в случае с составными выражениями, вместо знаков процента ( % ) использовать восклицательные знаки и предварительно включить режим связывания времени выполнения командой SETLOCAL ENABLEDELAYEDEXPANSION. Таким образом, наш пример следует переписать следующим образом:

SETLOCAL ENABLEDELAYEDEXPANSION
SET a=
FOR %%i IN (Раз,Два,Три) DO SET a=!a!%%i
ECHO a=%a%

В этом случае на экран будет выведена строка «a=РазДваТри».

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Honor 10 driver windows 10
  • Как убрать временный профиль в windows 10
  • Выполнен выход из windows search
  • Как отключить оптимизацию доставки в windows 10 навсегда через командную строку
  • Недостаточно памяти для обработки команды windows 7 как исправить