Бат-файлы ведут свою историю со времен 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-файлах с использованием ограниченного набора внешних команд может быть интересным упражнением.

Комментарии (41)


  1. DistortNeo
    22.02.2022 17:28
    +19

    Зашёл, чтобы увидеть ответ на вопрос "Какие задачи не решаются bat-файлами?"

    Ответа не увидел.


    1. PereslavlFoto
      22.02.2022 20:40

      Пример: этим способом трудно получить год из даты (при условии, что формат даты неизвестен).


      1. dmitryvolochaev Автор
        22.02.2022 20:44
        +4

        А как вообще работать с датой, если формат неизвестен? Допустим, 11/12/14. Какой тут год? 2014? 2011? А, может, 2012?


        1. PereslavlFoto
          22.02.2022 20:58

          В других средах можно узнать формат даты или просто получить год. А вот в bat-файлах узнать всё это труднёхонько.

          Вход возникает не просто так, он записан в переменной %DATE%. Поэтому в общем случае можно получить год через какую-то функцию. Но в бат-файлах так не поступить очень трудно.


          1. Magnum72
            22.02.2022 21:13
            +4

            for /f "tokens=2 delims==" %%I in ('wmic os get localdatetime /format:list') do set datetime=%%I
            set Yr=%DateTime:~0,4%
            set Mon=%DateTime:~4,2%
            set Day=%DateTime:~6,2%
            set Hr=%DateTime:~8,2%
            set Min=%DateTime:~10,2%
            set Sec=%DateTime:~12,2%
            echo Datetime: %Yr%-%Mon%-%Day% %Hr%:%Min%:%Sec%


            1. dmitryvolochaev Автор
              22.02.2022 21:16

              Жаль, wmic скоро исчезнет, и этот код перестанет работать


              1. NN1
                22.02.2022 21:36

                Чем решение через powershell не угодило ? Сегодня он есть везде.

                Есть ещё вариант через js/vbs

                WScript.Quit(Year(Now))
                >cscript /nologo a.vbs
                >echo %errorlevel%
                2022


                1. jurok04
                  23.02.2022 16:31
                  +1

                  В наших краях работает такое (утянуто из stackoverflow):

                  setlocal enabledelayedexpansion
                  :: Extract date fields - language dependent
                  for /f "tokens=1-4 delims=/-. " %%i in ('date /t') do (
                          set v1=%%i& set v2=%%j& set v3=%%k
                          if "%%i:~0,1%%" gtr "9" (set v1=%%j& set v2=%%k& set v3=%%l)
                  
                          for /f "skip=1 tokens=2-4 delims=(-)" %%m in ('echo.^|date') do (
                              set %%m=!v1!& set %%n=!v2!& set %%o=!v3!
                      )
                  )
                  
                  :: Final set for language independency (English and Portuguese - maybe works for Spanish and French)
                  set year=%yy%%aa%
                  set month=%mm%
                  set day=%dd%
                  
                  :: Test date
                  echo %day%/%month%/%year%
                  


                  1. dmitryvolochaev Автор
                    23.02.2022 16:47
                    +1

                    В ваших краях - это где, если не секрет? Этот код предполагает, что date в приглашении для ввода использует обозначения yy, mm и dd для формата. А для русского языка, видимо, надо делать set year=%гг%&& set month=%мм%&& set day=%дд%. И не забывайте сохранять файл в кодировке 866. Как-то так


                1. horror_x
                  23.02.2022 23:50

                  Чем решение через powershell не угодило?
                  С ним тоже не всё гладко. Навскидку:
                  1. Требует при запуске переопределять параметры безопасности, ещё желательно указывать флаги вроде -NoProfile для ускорения запуска.
                  2. Даже с флагами запускается иногда несколько секунд (!).
                  3. Надо писать код под минимально возможную версию (чтобы работало на всех ОС), а за этим тяжело следить и добавляется необходимость тестировать в других средах.


                  1. NN1
                    23.02.2022 23:54

                    Я имел ввиду конкретно получить дату, а не весь скрипт писать.

                    Так, по пунктам согласен. PS запускается нереально долго.

                    А разные версии это та ещё головная боль когда подключаешься к другой машине через PS Remoting и там более старая версия без каких-то нужных фич:)

                    Зато если можно притащить PowerShell Core то там и быстрый запуск и современные удобства языка но увы он не встроен в систему.


            1. PereslavlFoto
              22.02.2022 21:31

              Да, решение через постороннюю программу wmic мне встречалось. К сожалению, эта программа доступна не во всех DOS-оболочках.


              1. AbnormalHead
                23.02.2022 20:52
                +2

                Вариант, который работает начиная от XP до Win10.

                for /f "skip=2 tokens=2*" %%i in ('reg QUERY "HKCU\Control Panel\International" /v sDate') do set sdate=%%j
                for /f "delims=%sdate% tokens=1,2,3" %%i in ("%DATE%") do call :getpackage %%i %%j %%k
                
                echo %package%
                
                goto :EOF
                 
                :getpackage
                set day=%1
                set month=%2
                set /a year=%3
                if %day% leq 9 set day=0%day%
                if %month% leq 9 set month=0%month%
                set package=%year%-%month%-%day%
                goto :EOF 
                


                1. dmitryvolochaev Автор
                  23.02.2022 20:57

                  Интересно. А что если в delims тупо перечислить все возможные разделители вместо того, чтобы читать реестр?


                1. PereslavlFoto
                  24.02.2022 01:34
                  +1

                  Сначала мы в %sdate% получаем разделитель.

                  Потом мы читаем дату и разделяем её разделителем, получаем части даты.

                  Потом мы считаем, что первая часть даты — день, а третья часть даты — это год. Но почему мы так решили?

                  Дата может быть не только dd mm yyyy, она может оказаться mmm dd yyyy (Фев 24 2022) или даже yyyy mmm dd (2022 Фев 24).


      1. Germanjon
        23.02.2022 11:21

        Можно написать программу на С/С++/Питон и вызвать её из Bat-файла


    1. KvanTTT
      22.02.2022 22:05
      +2

      Видимо никакие, т.к. язык тьюринг-полный?


    1. Myxach
      23.02.2022 00:44

      Дум врятли можно написать на .bat файлах


      1. Format-X22
        23.02.2022 02:57

        Смотря на каком уровне абстракций... На зубной щётке было с небольшим железным бонусом, но таки работало.


    1. Bedal
      23.02.2022 10:27
      +1

      unc-адреса убивают всякую возможность пользоваться ВАТ-ами.


  1. BiW
    22.02.2022 18:00
    +4

    В свое время один уникум умудрился даже "антивирус" на батниках написать))


  1. maksl
    22.02.2022 18:40
    +3

    эмм. вся суть статьи может уместиться в паре-тройке строчек?

    c:\help

    c:\for /?

    c:\if /?


    1. dmitryvolochaev Автор
      22.02.2022 18:44
      +1

      Ну, может, еще, set /?, goto /?, exit /?, call /?


  1. NN1
    22.02.2022 19:12

    Не нужно !%A%!, надо !A!.

    Полезный ресурс

    https://ss64.com/nt/syntax.html


    1. dmitryvolochaev Автор
      22.02.2022 19:26
      +1

      Это чтобы получить значение А, надо !А!. А тут я говорю о псевдомассивах, которые по вашей же ссылке тоже описаны https://ss64.com/nt/syntax-arrays.html


      1. NN1
        22.02.2022 19:31

        Ок. Стоило тогда добавить более содержательный пример вместо простого !%A%!.


  1. ugenk
    22.02.2022 22:15
    +1

    Ностальгично вспомнил времена самописного autoexec.bat, спасибо :-)


  1. Serge78rus
    22.02.2022 22:43
    +2

    Первое место с bat-файлами делят PowerShell и bash
    Если бы возможности bat-файлов можно было сравнивать с bash, то PowerShell бы не появился, ибо был бы не нужен.


    1. unsignedchar
      22.02.2022 23:08

      PowerShell бы появился вне зависимости от наличия bash. Bash без кучи утилит, работающих через пайп, не сильно полезен.


  1. adeshere
    23.02.2022 02:54
    +2

    Спасибо, что не забываете о первоистоках ;-))

    Я прям аж детскую молодость вспомнил. 1988 год, IBM PC XT, DOS фортран, из интерфейса только командная строка на черном экране... Я тогда "изобрел" для себя IDE на bat-никах, которой потом и пользовался довольно многие годы. С компилятором, отладчиком и редактором кода OMNI....

    Под спойлером уже чуть более продвинутая версия этой "IDE" (фактически 1991 года с небольшими добавлениями 1992-1994). А exe-шники мы тогда сжимали в SFX-архивы (с автозапуском распакованной проги) для экономии места на диске... простите, дискете ;-)

    IDE на bat-файлах

    @echo off
    rem █████████████████████████████████████████████████████████████
    rem ███ Командный файл MST.BAT имитирует "турбо"-режим ███
    rem ███ при отладке программ на MS -фортране. ███
    rem █████████████████████████████████████████████████████████████
    rem
    echo [32;40m
    if [%1]==[] goto :help
    if [%1]==[/help] goto :help
    if [%1]==[/HELP] goto :help
    if exist %1.for goto :ask
    echo Ошибка: отсутствует файл %1.for -- отладка невозможна.
    goto :quit1
    :help
    echo [32;40m
    cls
    echo ████████ MS/FORTRAN "АВД", №1991-94, v 8.00. ████████
    echo . . .
    echo Командный файл MST.BAT позволяет отлаживать программы на
    echo MS-фортране: собирать, запускать задачи, вызывать Code View для
    echo трассирования, просматривать и редактировать входные и выходные
    echo файлы вашей программы и т.п. При этом вместо массы различных
    echo команд Вам потребуется всего одна команда:
    echo "MST имя-Вашей-программы"
    echo Например, если ваша программа называется PROGRAM.FOR, вы должны
    echo набрать:
    echo "MST PROGRAM"
    echo . . .
    echo . . .
    echo Командный файл MST.BAT написан в КСЭ ИФЗ АН СССР Дещеревским А.В.
    echo MST.BAT ссылается на MS-FORTRAN v5.0 и утилиты Code View, NC,
    echo CHOICE, AINEXE и редактор OMNI. Для работы необходимо
    echo предварительно установить переменные окружения %FL0% и %MSLIB%.
    echo Инструкцию по применению MST.BAT см. в файле BAT.HLP.
    echo . . .
    choice /c:g . Продолжать
    if not exist %1.for goto :quit
    :ask
    if exist %1.obj del %1.obj
    cls
    echo ████████ MS/FORTRAN "АВД", №1991-94, v 7.26. ████████
    echo Отладка программы %1:
    echo . . .
    echo Введите ключ:
    echo "e" - редактировать исходный текст программы %1.for;
    echo "l" - редактировать командный файл линкера %1.lnk;
    echo "c" - вывести листинг трансляции на терминал;
    echo "m" - скомпилировать программу (собрать EXE-файл);
    echo "r" - запустить программу (готовый .EXE-файл);
    echo "d" - собрать запустить программу под управлением Code View;
    echo "p" - уплотнить EXE-файл: ainexe %1.EXE
    echo "t" - посмотреть дополнительное описание MST.BAT;
    echo "q" - кончить отладку программы (вернуться в DOS).
    :ask_1 e,l,c,m,r,d,p,t,q,h
    choice /c:elcmrdptqh
    if errorlevel 10 goto :ask
    if errorlevel 9 goto :quit
    if errorlevel 8 goto :help
    if errorlevel 7 goto :ainexe
    if errorlevel 6 goto :debug
    if errorlevel 5 goto :run
    if errorlevel 4 goto :make
    if errorlevel 3 goto :compil
    if errorlevel 2 goto :gedit
    :edit
    if exist %1.obj del %1.obj
    omni %1.for
    goto ask_1
    :gedit
    omni %1.lnk
    goto ask_1
    :compil
    echo [32;40m
    cls

        %fl0% /c %1.for %mslib%
    
        goto ask_1
    

    :debug
    cls
    if exist %1.exe del %1.exe
    %fl0% /Zi /Zd %1.for %mslib% /link /SEG:512
    if not errorlevel 0 goto :ask_1
    if exist %1.exe cv %1
    echo [32;40m
    goto ask_1
    :make
    if exist %1.exe del %1.exe
    %fl0% %1.for %mslib% /link /SEG:512
    goto :ask_1
    :run cls
    if exist %1.obj del %1.obj
    if exist %1.exe %1
    echo [32;40m
    goto :ask_1
    :ainexe
    if exist %1.exe ainexe %1.exe
    if exist %1.old del %1.old
    goto ask_1
    :quit
    echo [32;40m
    cls
    if exist %1.obj del %1.obj
    if exist %1.lst del %1.lst
    :quit1

    Еще были аналогичные bat-ники для библиотек (причем исходные модули хранились в архиве и извлекались оттуда для редактирования/компиляции), многопользовательского логина (да-да, в среде DOS ;-), и т.д. т.п. - всего штук 20 таких "утилит" на все случаи жизни. Интересные были времена ;-)


    1. dmitryvolochaev Автор
      23.02.2022 10:57

      Круто. А я-то во времена MS DOS из всех IDE знал только debug.com


  1. d1gital_love
    23.02.2022 14:22
    +1

    Очень поверхностно, почти ничего нового и не актуально.

    Windows PowerShell нельзя сравнивать с большинством UNIX shell и bat-ами.


  1. d1gital_love
    23.02.2022 14:34

    Почему нет источников вообще?

    Документация по этому была всегда.


  1. klvov
    23.02.2022 14:44
    +1

    Сам грешен, иногда на батниках разные скрипты делаю, для личного использования. Правда, если скрипт разрастается, то код становится очень непонятным, и тогда приходится переписывать его на Java, Python или другом "нормальном языке программирования".

    А статья хорошая, спасибо. Про %date% и %cd% вот я даже не знал. Можно ещё добавить про shift - это способ, когда в батник надо передать больше 9 аргументов командной строки (%1, %2, вот это вот)


    1. dmitryvolochaev Автор
      23.02.2022 14:49
      +2

      Я никогда не использовал shift. А разобрать произвольное количество параметров можно еще через for %%a in (%*)


  1. gapel
    23.02.2022 16:54
    +2

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

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

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


    1. NN1
      23.02.2022 23:58
      +1

      кстати есть ещё вариант полиглотного файла если нужно простое развёртывание в виде одного файла:

      https://github.com/fireflyoo/polyglot/blob/master/Python.py.bat

      
      


  1. neokoder
    24.02.2022 07:03
    +1

    Как можно вставить символы в бат файл? Допустим я хочу вот эти символы вместо текста


    1. dmitryvolochaev Автор
      24.02.2022 07:18

      Прямо так и вставить как есть. На сколько я знаю, cmd не поддерживает никакие коды типа \0x123. И не забываем, что кодировка для батников - 866. Как в DOS. Никакого вам тут юникода.

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


      1. horror_x
        24.02.2022 08:52
        +1

        Вот только где найти текстовый редактор с функцией вставки таких символов?
        Alt+027 в Notepad++ отрабатывает.


      1. roqin
        24.02.2022 09:41
        +1

        >кодировка для батников - 866

        Хотел уж сказать "а вот и нет - есть еще chcp 65001", но решил проверить выведя после этой команды потом что-то типа "echo ᾩᴆᵷ", но cmd.exe вываливается, PowerShell тоже вываливается с ошибкой и только ConEmu выводит "ᾩᴆᵷ". Короче, я даже не знаю что сказать ????