Вот эта картинка создана .bat файлом:
Многие не знают, но если приложить немного усилий, то командный процессор MS Windows становится способен на многое. В принципе, это обычный императивный язык программирования, немного со странностями, но именно они превращают программирование на нём в своеобразное развлечение. Многие действия, не предусмотренные в конструкции языка, надо придумать как имитировать, порой какими-то фантастическими способами.
Например, как сделать паузу на заданное количество секунд? Команда pause тут бессильна. В место неё паузу удобно организовать через ping.
Пауза на 5 секунд будет выглядеть вот так:
ping 127.0.0.1 -n 6 -w 1000 > nul
Вот как узнать, содержит ли строка подстроку? Опять же, на первый взгляд ничего подходящего нет. На помощь приходит замена подстроки в строке:
set string=SOME TEXT
if not "%string%"=="%string:TEXT=%" echo YES
Ещё на .bat можно организовать вычисления с плавающей точкой (изначально плавающая точка не поддерживается), распараллеленные вычисления, синхронизацию между «процессами», распараллеленное вычисление на нескольких компьютерах и т.п. Я как-то раз видел исходники полиморфного(!) вируса, который полностью написан на bat-файле :)
В общем, время от времени я пишу что-нибудь на .bat, не могу пройти мимо такого вызова :)
Cейчас выкладываю одну из своих работ: батник, который рендерит множество Мандельброта в bmp.
@echo off
set /a xPixels = 180
set /a yPixels = 120
set /a xStart = -22000
set /a yStart = -10000
set /a xSize = 32000
set /a ySize = 20000
set /a maxIter = 32
call ::make_bmp_header
set /a xStep = xSize/xPixels
set /a yStep = ySize/yPixels
set /a iy = 0
:iyLoop
set /a ix = 0
:ixLoop
set /a x = xStart + ix * xStep
set /a y = yStart + iy * yStep
set /a x0 = x
set /a y0 = y
set /a iteration = 0
:formula
set /a xtemp = x*x/10000 - y*y/10000 + x0
set /a y = 2*x*y/10000 + y0
set /a x = xtemp
set /a iteration+=1
set /a dist = x*x/10000 + y*y/10000
if [%iteration%]==[%maxIter%] goto breakFormula
if /I %dist% LEQ 40000 goto :formula
:breakFormula
if [%iteration%]==[%maxIter%] (call :plot_black) else (call :plot_color %iteration%)
set /a ix += 1
if not [%ix%]==[%xPixels%] goto ixLoop
set /a progress = yPixels - iy
echo.%progress%
set /a iy += 1
if not [%iy%]==[%yPixels%] goto iyLoop
call ::make_bin
ren file$ result.bmp
mspaint result.bmp
exit/b
:plot_black
call :write_byte 0
call :write_byte 0
call :write_byte 0
exit/b
:plot_color
set /a rc=%1*5 + 32
set /a gc=%1*7 + 6
set /a bc=128 - (%1*3 + 4)
call :write_byte %rc%
call :write_byte %gc%
call :write_byte %bc%
exit/b
:make_bmp_header
set /a dataSize = xPixels * yPixels * 3 + 54
set /a dataSize0 = dataSize%%256
set /a dataSize1 = (dataSize/256)%%256
set /a dataSize2 = (dataSize/(256*256))%%256
set /a dataSize3 = (dataSize/(256*256*256))%%256
call :init_bin
call :write_byte 66
call :write_byte 77
call :write_byte 118
call :write_byte 56
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 54
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 40
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte %xPixels%
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte %yPixels%
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 1
call :write_byte 0
call :write_byte 24
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte %dataSize0%
call :write_byte %dataSize1%
call :write_byte %dataSize2%
call :write_byte %dataSize3%
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
call :write_byte 0
exit /b
:init_bin
echo.n file$>bin$
set /a addr=0x0100
call set "hstr=e "
call :write_word %addr%
set mustflush=0
exit /b
:write_byte
set /a a=%1
set hexs=0123456789ABCDEF
set /a a0=a/16
set /a a1=a%%16
call set res= %%hexs:~%a0%,1%%%%hexs:~%a1%,1%%
set hstr=%hstr%%res%
set /a addr+=1
set /a mod16=addr%%16
set mustflush=1
if not %mod16%==0 exit /b
echo.%hstr%>>bin$
call set "hstr=e "
call :write_word %addr%
set mustflush=0
exit /b
:write_word
set /a a=%1
set hexs=0123456789ABCDEF
set /a a0=a/4096
set /a a1=a/256%%16
set /a a2=a/16%%16
set /a a3=a%%16
call set res=%%hexs:~%a0%,1%%%%hexs:~%a1%,1%%%%hexs:~%a2%,1%%%%hexs:~%a3%,1%%
set hstr=%hstr%%res%
exit /b
:make_bin
if "%mustflush%"=="1" echo.%hstr%>>bin$
set /a filesz=addr-0x0100
echo.r cx>>bin$
set hstr=
call :write_word %filesz%
echo %hstr%>>bin$
echo.w>>bin$
echo.q>>bin$
debug<bin$
del bin$
exit /b
комментарии (102)
да уж… прям через одно место это делается… но радует что есть люди которые умеют выйти из ситуации :)
Когда делал игру «сокобан», приходилось учитывать разные версии командной строки.
(=
но время от времени заглядывал на разные сайты с tips and tricks
например, malektips.com/windows_xp_and_dos_help_and_tips.html
Никогда бы не подумал, что это возможно в принципе.
Майкросовский подход :)
И как юзать плавающую точку?
Да, это пожалуй самое оригинальное извращение из всех о которых я слышал =)
Да, отладочными echo.
А ещё, если не делать @echo off, то можно видеть какие команды исполняются и с какими параметрами. Для удобства, этот вывод можно перенаправить в файл для дальнейшего изучения.
>И как юзать плавающую точку?
Надо написать функции для работы с плавающей точкой =)
В этой програме я использовал фиксированную точку, 4 десятичных разряда для дробной части.
tinyurl.com/llkbsd
Это не новость для посвящённых. В славные 90-е вирмейкеры куда больше изощрялись, чем сейчас. :)
Интересующиеся могут полистать старые e-zines вирсцены.
во были времена, когда натыкался на эти выпуски, приятно вспомнить.
Растеризация треугольника в консоли:
www.everfall.com/paste/id.php?t5ht4mw6kvls
Консольный сокобан:
www.everfall.com/paste/id.php?szlzpnwtsftu
это автор топика видимо запостил)
«programming for fun»
Батник был запущен с сетевой расшарки на другом компе. Временных файлов на расшарке я не увидел :)
Ещё дело может быть в том, как cmd исполняет батники. Он их читает по командам (из-за этого батники можно менять в процессе исполнения)
Мне напоминает повернутые пики или раздутые трефы
что я делаю не так?
у меня на ноутбуке тоже где-то 20 минут работает.
Батник в любой папке лежать может?
Посмотри, чтобы там уже не было result.bmp
В строках
set /a xPixels = 180
set /a yPixels = 120
замени разрешение на меньшее, например 8 на 8, чтобы не ждать результата долго.
Есть ли у тебя mspaint.exe?
Есть ли у тебя команда debug?
Заметьте, ни одного заминусованного коммента к статье.
set /p var=Как Вас зовут?:
echo Hello, %var%
если не заработает, раскомментировать первую строчку
Если это нужно сделать в произвольный момент, то к сожалению, я не знаю простых способов.
Ждем Doom на cmd скриптах :)
Правда в Linux и с помощью специализированной программы Fraqtive.
С помощью пинга локалхоста задержки делать + (не могу пока).
В Windows7, не знаю как в Vista наконецто добавили
Examples:
TIMEOUT /?
TIMEOUT /T 10
TIMEOUT /T 300 /NOBREAK
TIMEOUT /T -1
Parameter List:
/T timeout Specifies the number of seconds to wait.
Valid range is -1 to 99999 seconds.
/NOBREAK Ignore key presses and wait specified time.
/? Displays this help message.
NOTE: A timeout value of -1 means to wait indefinitely for a key press.
вспоминаю молодость :)