Как стать автором
Обновить

Комментарии 53

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

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

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

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

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

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

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%

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

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

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

WScript.Quit(Year(Now))
>cscript /nologo a.vbs
>echo %errorlevel%
2022
В наших краях работает такое (утянуто из 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%

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

в начале .bat файла ставим

@rem UTF-8 encoding
@chcp 65001

и можно сохранять в UTF-8 кодировке (первая строка несет две функции - читаемость и, главное, в случае BOM интерпретатор ругается на всю такую строку, но, к счастью, идет дальше).

Прикольно. А нет ли команды для переключения шрифта? А то иероглифы, например, не во всех шрифтах есть. Нужно вручную правой кнопкой на заголовок окна, "свойства", "шрифт" делать

https://ru.wikihow.com/изменить-шрифт-в-командной-строке-Windows

там смотрим 8-й пункт:

Правой кнопкой мыши щелкните по верхней части (заголовку) окна командной строки и в меню выберите «Умолчания». Окно, которое откроется, будет абсолютно таким же, как окно «Свойства», но любые изменения, сделанные в данном окне, будут применены ко всем окнам командной строки (вне зависимости от ярлыка).

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

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

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

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

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

Да, решение через постороннюю программу wmic мне встречалось. К сожалению, эта программа доступна не во всех DOS-оболочках.
Вариант, который работает начиная от 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 

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

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

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

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

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

Можно так получить год или дату в любом формате в нужном часовом поясе:

for /F "usebackq tokens=*" %%F in (`powershell -Command "(Get-Date).ToUniversalTime().ToString('yyyyMMdd-HHmm')"`) do (
  set DT=%%F
)

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

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

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

Ой, я бы не был так уверен, что нельзя написать Doom на чисто батнике. Где-то я точно видел расчёты поворота 3d-матрицы с внесением в кеш каждого фрейма. Возможно, это был проект от Delphiist. Его вместе с другими играми можно найти в теме: https://www.cyberforum.ru/cmd-bat/thread1031910.html

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

Частично могут помочь pushd и popd. Вроде как не отменили команду net use. Хотя, конечно, это костыли.

Это почему? Подумаешь, нельзя сделать сетевую папку текущей. А в остальном всё работает (у меня Windows 10, если что): bat-файл в сетевой папке запускается и из проводника, и из командной строки, команда type выводит содержимое файла из сетевой папки, dir показывает содержимое сетевой папки, указанной в параметре, файл из сетевой папки открывается в Блокноте, если указать его в командной строке, и вообще, ограничения интерпретатора не относятся к внешним программам

Если вы это про зависимости, которые ваше приложение ищет в своей папке, то %~dp0 вам в помощь

запустить приложение, расположенное на сетевом ресурсе?

А без батников с этим проблем нет?

нет, конечно. Всё запускается и в файловых менеджерах, и в PShell'e, да где угодно.
Только BAT не умеет.

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

c:\help

c:\for /?

c:\if /?

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

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

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

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

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

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

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

Я прям аж детскую молодость вспомнил. 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 таких "утилит" на все случаи жизни. Интересные были времена ;-)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

команда

chcp 65001

и будет вам юникод (чуть подробнее выше)

Часто вижу в bat-файлах goto, проверки возвращаемых значений, метки:

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

:b
echo Inside b.bat
exit /B 1

На мой взгляд хорошая практика писать что-то такое:

call a.bat || exit /b 1
call b.bat || exit /b 1

Чтобы по первой ошибке скрипт завершался. Без меток код гораздо понятнее.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий