Бат-файлы ведут свою историю со времен 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)
maksl
22.02.2022 18:40+3эмм. вся суть статьи может уместиться в паре-тройке строчек?
c:\help
c:\for /?
c:\if /?
NN1
22.02.2022 19:12dmitryvolochaev Автор
22.02.2022 19:26+1Это чтобы получить значение А, надо !А!. А тут я говорю о псевдомассивах, которые по вашей же ссылке тоже описаны https://ss64.com/nt/syntax-arrays.html
Serge78rus
22.02.2022 22:43+2Первое место с bat-файлами делят PowerShell и bash
Если бы возможности bat-файлов можно было сравнивать с bash, то PowerShell бы не появился, ибо был бы не нужен.unsignedchar
22.02.2022 23:08PowerShell бы появился вне зависимости от наличия bash. Bash без кучи утилит, работающих через пайп, не сильно полезен.
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 таких "утилит" на все случаи жизни. Интересные были времена ;-)
dmitryvolochaev Автор
23.02.2022 10:57Круто. А я-то во времена MS DOS из всех IDE знал только debug.com
d1gital_love
23.02.2022 14:22+1Очень поверхностно, почти ничего нового и не актуально.
Windows PowerShell нельзя сравнивать с большинством UNIX shell и bat-ами.
klvov
23.02.2022 14:44+1Сам грешен, иногда на батниках разные скрипты делаю, для личного использования. Правда, если скрипт разрастается, то код становится очень непонятным, и тогда приходится переписывать его на Java, Python или другом "нормальном языке программирования".
А статья хорошая, спасибо. Про %date% и %cd% вот я даже не знал. Можно ещё добавить про shift - это способ, когда в батник надо передать больше 9 аргументов командной строки (%1, %2, вот это вот)
dmitryvolochaev Автор
23.02.2022 14:49+2Я никогда не использовал shift. А разобрать произвольное количество параметров можно еще через for %%a in (%*)
gapel
23.02.2022 16:54+2много работал с bat файлами на одной из работ лет 5 назад. На них писались управлялки для тестеров устройств. Потому что можно было пихать в автозапуски или спокойно подсовывать производству с инструкцией - "просто запусти, дальше оно самое все сделает и лог запишет".
Но по мере расширения функционала все больше склонялся к тому, что бат файл нужен чтобы запустить питоновский скрипт. Потому что на Питоне писалось и отлаживалось все гораздо быстрей и проще.
Собственно, сейчас бат файл как входная точка для сборки проекта, но по сути я теперь просто в нем проверяю наличие и версию тулзов, а потом все передаю питоновскому SCons.
NN1
23.02.2022 23:58+1кстати есть ещё вариант полиглотного файла если нужно простое развёртывание в виде одного файла:
https://github.com/fireflyoo/polyglot/blob/master/Python.py.bat
neokoder
24.02.2022 07:03+1Как можно вставить символы в бат файл? Допустим я хочу вот эти символы вместо текста
dmitryvolochaev Автор
24.02.2022 07:18Прямо так и вставить как есть. На сколько я знаю, cmd не поддерживает никакие коды типа \0x123. И не забываем, что кодировка для батников - 866. Как в DOS. Никакого вам тут юникода.
Кстати, то же приходится делать с символом с кодом 27 (десятичное), с которого начинаются коды ANSI-терминала. Он, как и псевдографика, обрабатывается как непробельный символ без особого значения в языке. Вот только где найти текстовый редактор с функцией вставки таких символов?
horror_x
24.02.2022 08:52+1Вот только где найти текстовый редактор с функцией вставки таких символов?
Alt+027 в Notepad++ отрабатывает.
roqin
24.02.2022 09:41+1>кодировка для батников - 866
Хотел уж сказать "а вот и нет - есть еще chcp 65001", но решил проверить выведя после этой команды потом что-то типа "echo ᾩᴆᵷ", но cmd.exe вываливается, PowerShell тоже вываливается с ошибкой и только ConEmu выводит "ᾩᴆᵷ". Короче, я даже не знаю что сказать ????
DistortNeo
Зашёл, чтобы увидеть ответ на вопрос "Какие задачи не решаются bat-файлами?"
Ответа не увидел.
PereslavlFoto
Пример: этим способом трудно получить год из даты (при условии, что формат даты неизвестен).
dmitryvolochaev Автор
А как вообще работать с датой, если формат неизвестен? Допустим, 11/12/14. Какой тут год? 2014? 2011? А, может, 2012?
PereslavlFoto
В других средах можно узнать формат даты или просто получить год. А вот в bat-файлах узнать всё это труднёхонько.
Вход возникает не просто так, он записан в переменной %DATE%. Поэтому в общем случае можно получить год через какую-то функцию. Но в бат-файлах так не поступить очень трудно.
Magnum72
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%
dmitryvolochaev Автор
Жаль, wmic скоро исчезнет, и этот код перестанет работать
NN1
Чем решение через powershell не угодило ? Сегодня он есть везде.
Есть ещё вариант через js/vbs
jurok04
В наших краях работает такое (утянуто из stackoverflow):
dmitryvolochaev Автор
В ваших краях - это где, если не секрет? Этот код предполагает, что date в приглашении для ввода использует обозначения yy, mm и dd для формата. А для русского языка, видимо, надо делать set year=%гг%&& set month=%мм%&& set day=%дд%. И не забывайте сохранять файл в кодировке 866. Как-то так
horror_x
1. Требует при запуске переопределять параметры безопасности, ещё желательно указывать флаги вроде -NoProfile для ускорения запуска.
2. Даже с флагами запускается иногда несколько секунд (!).
3. Надо писать код под минимально возможную версию (чтобы работало на всех ОС), а за этим тяжело следить и добавляется необходимость тестировать в других средах.
NN1
Я имел ввиду конкретно получить дату, а не весь скрипт писать.
Так, по пунктам согласен. PS запускается нереально долго.
А разные версии это та ещё головная боль когда подключаешься к другой машине через PS Remoting и там более старая версия без каких-то нужных фич:)
Зато если можно притащить PowerShell Core то там и быстрый запуск и современные удобства языка но увы он не встроен в систему.
PereslavlFoto
Да, решение через постороннюю программу wmic мне встречалось. К сожалению, эта программа доступна не во всех DOS-оболочках.
AbnormalHead
Вариант, который работает начиная от XP до Win10.
dmitryvolochaev Автор
Интересно. А что если в delims тупо перечислить все возможные разделители вместо того, чтобы читать реестр?
PereslavlFoto
Сначала мы в %sdate% получаем разделитель.
Потом мы читаем дату и разделяем её разделителем, получаем части даты.
Потом мы считаем, что первая часть даты — день, а третья часть даты — это год. Но почему мы так решили?
Дата может быть не только dd mm yyyy, она может оказаться mmm dd yyyy (Фев 24 2022) или даже yyyy mmm dd (2022 Фев 24).
Germanjon
Можно написать программу на С/С++/Питон и вызвать её из Bat-файла
KvanTTT
Видимо никакие, т.к. язык тьюринг-полный?
Myxach
Дум врятли можно написать на .bat файлах
Format-X22
Смотря на каком уровне абстракций... На зубной щётке было с небольшим железным бонусом, но таки работало.
Bedal
unc-адреса убивают всякую возможность пользоваться ВАТ-ами.