2009-01-10:

Skrypty .BAT i programowanie obiektowe

bat:windows:medium
UPDATE: Zgodnie z obietnicą (z końca tego postu) wrzuciłem post o OpenGL w .BAT.

Dzisiejszy post jest w sumie fragmentem mojego wykładu o skryptach .BAT (tego z wyklady.net), więc jeżeli ktoś był obecny na owym wykładzie, to raczej niczego nowego się nie dowie.

Skrypty .BAT (lub batch, jak kto woli) są stare jak DOS - pierwszy raz spotkałem się z nimi na starym 286, i były w powszechnym użytku wtedy. Chciałeś uruchomić grę na Herkulesie (czarno biała karta graficzna o dość niestandardowej rozdzielczości 720 x 348)? To musiałeś naklepać skrypcik odpalający emulator CGA (większość gier chodziło w tym trybie), potem gierkę, a potem wyłączający emulację. Skrypcik wyglądał mniej więcej tak:

color 5
gra.exe
color 7


Potem nadeszły czasy walki o każdy dodatkowy kilobajt pamięci operacyjnej, XMSa i EMSa, czasy w których każdy miał po kilka zestawów skryptu startowego autoexec.bat i config.sys (lub jeden skrypt oparty o menu wyboru). A potem nadszedł Windows 95, 98, DirectX, i skrypty .BAT przestały interesować normalnych użytkowników (a teraz przyszedł Monad aka Windows PowerShell, i .BAT przestaje interesować nawet tzw. power userów).

OK, koniec tej historii. Teraz o programowaniu obiektowym w .BAT.

Jak wiadomo .BAT trudno posądzić o jakieś większe możliwości. Niby ma goto, całkiem potężną pętle for, wywołania funkcji za pomocą call, no i zmienne do których można odwołać się na dwa sposoby (%normalnie% lub !z_opóźnionym_odczytem_wartości! - trzeba pamiętać iż aby użyć opóźnionego rozwijania wartości trzeba na początku skryptu wrzucić setlocal enabledelayedexpansion, lub ustawić klucz {HKLM,HKCU}\Software\Microsoft\Command Processor\DelayedExpansion na 1 (DWORD)). Ale klasy? Nope. Klas nie ma, więc o programowaniu obiektowym trudno w ogóle mówić. Natomiast, okazuje się że klasy/obiekty można emulować, i to nawet dość skutecznie.

Całość opiera się o mechanizm zmiennych - tych zmiennych które ustawiamy set nazwa=wartosc, i do których odwołujemy się za pomocą podanych wyżej wyrażeń z % lub !. Rozważmy następujący przykład:

set a=ver
echo %a%


Interpreter cmd.exe (bo on jest odpowiedzialny za wykonywanie .BAT) otworzy plik z powyższym skryptem, odczyta linię, zapamięta pozycję, zamknie plik (serio, dokładnie tak to wygląda, plik jest na nowo otwierany dla każdej linii, za wyjątkiem wyrażeń w nawiasach / z nawiasami, które są wczytywane w całości), po czym sprawdzi czy są w linii jakieś zmienne, podmieni je na ich wartości, i wykona linie. Oczywiście w pierwszej linii jest tylko ustawienie zmiennej środowiskowej a na wartość ver, więc zmiennych do podmiany nie ma. Natomiast w przypadku drugiej linii taka podmiana już zajdzie, i do wykonania trafi nie echo %a%, a echo ver. Zmieńmy trochę kod - wywalmy echo:

set a=ver
%a%


W tym przypadku do wykonania w drugiej linii trafi polecenie ver, które zostanie poprawnie wykonane, tak jakby autor skryptu napisał po prostu ver a nie %a%. W zmiennych można więc przechowywać nie tylko pojedyncze wyrazy, ale i całe polecenia.

A teraz, użyjmy tego mechanizmy do stworzenia klasy która odczytuje plik tekstowy do tablicy (w .BAT nie ma tablic jako takich, ale można je emulować, analogicznie do tych w skrypcie mIRC'a).
Załóżmy że klasa będzie nazywać się Plik, i jej konstruktor (czy też bardziej fabryka), również będzie tak się nazywać. Klasa będzie posiadać następujące zmienne/pola/zwał jak zwał:

lines - tablica zawierająca linie
name - zmienna zawierająca nazwę pliku
count - zmienna zawierająca ilość wczytanych linii

oraz następujące metody:

read - odczyt wskazanego pliku

Zacznijmy od konstruktora, który przyjmie dwa parametry - docelową nazwę obiektu, oraz nazwę pliku do oczytania:

:Plik
set %1.name=%2
set %1.read=call :Plik.read %1
goto :EOF


Linia pierwsza to oczywiście etykieta (label) oznaczająca miejsce w skrypcie. W drugiej linii jest ciekawa konstrukcja - tworzymy nazwę zmiennej używając pierwszego parametru, oraz sufiksu .name, i tejże zmiennej ustawiamy wartość przepisaną z parametru drugiego (nazwę pliku). Trzecia linia to "podlinkowanie" metody do obiektu, a tak na prawdę stworzenie zmiennej o nazwie obiekt.read która będzie zawierać polecenie call :Plik.read obiekt - czyli w pierwszym parametrze niejawnie (dla końcowego użytkownika) zostanie przekazana nazwa obiektu, którą możemy rozumieć jako pointer na obiekt (takie this, czy self). Czwarta linia to .BAT'owski return.

Przykładowe wywołanie konstruktora wygląda następująco:

call :Plik a ala.txt

Po tym wywołaniu zostanie utworzony obiekt a, i zostaną utworzone dwie dodatkowe zmienne związane z tym obiektem:
a.name=ala.txt
a.read=call :Plik.read a

Teraz użytkownik musi wywołać odczyt pliku wpisując po prostu %a.read%. Sama implementacja odczytu wygląda następująco:

:Plik.read
set j=0
for /f "delims=" %%i in ('type !%1.name!') do (
 set %1.lines.!j!=%%i
 set /a j=!j!+1
)
set %1.count=%j%
goto :EOF


Pierwsza linia to oczywiście nazwa metody - kropka oczywiście jest częścią nazwy, nie jest to żaden specjalny znak, po prostu użyłem go jako separatora nazwy klasy od nazwy metody czy pola, równie dobrze zamiast kropki mogła by tam być podłoga aka underscore (znak _). Potem mamy standardową funkcję for, która wykonywana jest dla każdej linii z pliku !%1.name! (gdzie %1 to nazwa obiektu, więc to jest !a.name! w naszym przypadku, co jest zamieniane na ala.txt). W pętli do "tablicy" o nazwie %1.lines.!j! - czyli w naszym przypadku będzie to a.lines.0, a.lines.1 etc - wrzucana jest każda kolejna linia pliku. Potem jest standardowa inkrementacja set /a j=!j!+1, i koniec pętli. Po pętli ustawiane jest jeszcze pole a.count na %j%, czyli ostateczną liczbę linii odczytanych z pliku, i następuje powrót.

Jak wygląda wykorzystanie tak przygotowanej klasy? Sprawa jest prosta:

call :Plik a ala.txt
%a.read%
echo Ilosc linii  : %a.count%
echo Druga linia  : %a.lines.1%
echo Trzecia linia: %a.lines.2%

goto :EOF


OK, mamy klasę i obiekt. Ale co z pointerami na obiekty? Sprawa jest raczej prosta, i zilustruje ją poniższy przykład:

@echo off

call :Plik a ala.txt
%a.read%

call :Plik b beata.txt
%b.read%

echo Plik A: %a.name%
echo Plik B: %b.name%

set ptr=a
echo Plik *Ptr: %%ptr%.name%
set ptr=b
echo Plik *Ptr: %%ptr%.name%

goto :EOF


Jak widać konstrukcja z zagnieżdżonymi zmiennymi rozwiązuje problem pointerów.

OK dalej. Teraz czas na dziedziczenie. Dziedziczenie akurat w językach tego typu jest dość proste - wszystko jest kwestią wywołania w fabryce/konstruktorze klasy dziecka, fabryki klasy matki - ona ustawi wszystkie metody, etc, a dziecko potem "poprawi" co mu się podoba.
Pokazany poniżej program zawiera klasę Figura z której wywodzą się dwie klasy - Kwadrat oraz Trojkat:


@echo off

call :Kwadrat a 10
call :Trojkat b 10 5

!a.pole!
!b.pole!
echo Klasa matka: a !a.matka!, b !b.matka!

set ptr=a
!%ptr%.pole!

set ptr=b
!%ptr%.pole!

goto :EOF


rem Klasa : Figura nazwa_obiektu a b
rem Metody: Figura, pole (wirtualna)
rem Pola  : a, b

:Figura
set %1.a=%2
set %1.b=%3
set %1.matka=Figura
goto :EOF


rem Klasa : Kwadrat nazwa_obiektu a b (dziedziczy Figura)
rem Metody: Kwadrat, pole
:Kwadrat
rem Wywolaj super konstruktor
call :Figura %*
set %1.pole=call :Kwadrat.pole %1
goto :EOF

:Kwadrat.pole
set /a pole=!%1.a! * !%1.a!
echo Pole kwadratu %1: %pole%
goto :EOF


rem Klasa : Trojkat nazwa_obiektu a b (dziedziczy Figura)
rem Metody: Trojkat, pole
:Trojkat
rem Wywolaj super konstruktor
call :Figura %*
set %1.pole=call :Trojkat.pole %1
goto :EOF

:Trojkat.pole
set /a pole=!%1.a! * !%1.b! / 2
echo Pole trojkata %1: %pole%
goto :EOF


No i w sumie tyle na dzisiaj. W następnym poście pokaże jak w .BAT napisać programik pod OpenGL ;>

P.S. i tak nie polecam obiektowego .BAT do większych projektów ;D

Comments:

2009-01-14 01:55:37 = kicaj
{
no stary pojechał żeś po bandzie
respect
}
2009-01-14 02:56:05 = Gynvael Coldwind
{
@kicaj
Cieszę się że się podoba ;D
}
2009-01-14 03:48:18 = Raccoon
{
Znalazłem taki błąd:
ktoś był obecny na ów wykładzie
powinno być
ktoś był obecny na owym wykładzie
Pozdr
}
2009-01-14 03:51:46 = Gynvael Coldwind
{
@Raccoon
Thx fixed ;>
}
2009-01-14 04:14:54 = zx
{
W końcu. :D To może teraz uda mi się napisać ten skrypcik do zmiany nazw wielu plików naraz...
}
2009-01-14 06:57:38 = Adaslaw
{
Może dodaj swoją obiektową wersję do zbioru:
http://99-bottles-of-beer.net/
?
;]
}
2009-01-14 07:06:55 = Jurgi
{
To ja poproszę jeszcze to samo w Basicu… :)
}
2009-01-14 07:27:38 = prs
{
Pisanie o obiektowych skryptach .bat świadczy tylko o jednym..
O całkowitym niezrozumieniu zasad dot. programowania obiektowego. Ale nie ma się czym przejmować... większość programistów tak naprawdę ich nie rozumie. Stąd też zdarzają się takie 'perełki'. :)
Jednak sam artykuł jest dosyć ciekawy.. pomijając terminologię w nim użytą. :)
pozdrawiam.
}
2009-01-14 08:27:01 = mikexcr
{
prs pierdolisz czlowieku, zazdroscisz mu wiedzy i jest Ci przykro. Idź sie gdzie indziej dowartosciowac, moze najlepiej idz na #gentoo-pl i z rejnem filozofuj...
}
2009-01-14 11:02:33 = korro
{
@prs: artykuł pokazuje realizację pseudo-obiektowości w oparciu o mechanizmy dostępne w DOS.

Moim zdaniem, autor wykazał się dobrą znajomością zarówno nowoczesnych i starszych języków programowania oraz historii systemu operacyjnego DOS...też pamiętam menu wyboru w autoexecu i configu :]

Pozdrawiam.
}
2009-01-14 11:30:21 = Gynvael Coldwind
{
@zx
Powodzenia ;>

@Adaslaw
Hmm, mówisz że warto? Wyślę zapytanie do maintainerów ;> Jeżeli dadzą zielone światło to wrzucę ;>

@Jurgi
Którym ? Amstradowym ? Hmm... jeżeli działa tak jak myślę, to jest do zrobienia ;> (nie mylić z "łatwe do zrobienia").

@prs
Ah, no i mnie zaciekawiłeś ;> Gdybyś mógł napisać (z cytatami z artykułu) które konkretnie użycia terminologii są (wg Ciebie) nieprawidłowe, oraz wyjaśnić dlaczego ;> Sądzę że sporo osób na tym skorzysta (w tym ja ;>) ;>

@mikexcr
Hehe nie ma potrzeby tak ostro ;> A nóż się czegoś nowego nauczymy (gdy tylko prs poda konkretny) ;>

@korro
Dziękuje ;>

@Wszyscy
Dzięki za komentarze ;> Sporo dzisiaj komentarzy ;>
Chciałbym jeszcze sprecyzować jedną rzecz. Mianowicie emulacja obiektowości którą opisuję w artykule nie jest skierowana dla wersji DOSowej .BAT. Prawdopodobnie w wersji DOSowej .BAT w ogóle nie ruszy (afair nie było tam deleyed expansion). Język .BAT jest implementowany w cmd.exe w nowych Windowsach, i w każdym Windowsie jest jakaś zmiana, tak że język się nadal rozwija. Natomiast nie ma już dużo wspólnego z DOSem ;>
Z DOSem natomiast miała sporo wspólnego implementacja .BAT znajdująca się w command.com (patrz np Windows XP, są tam DWA interpretery .BAT - 32 bitowy cmd.exe, i działający na NTVDM 16-bitowy command.com). Szczerze, nie testowałem emulacji obiektowości tam ;>
}
2009-01-14 12:25:16 = KKKas
{
Sporo komentarzy, bo zostałeś wykopany: http://www.wykop.pl/link/131963/programowanie-obiektowe-w-skryptach-bat

Ale to pewnie już zobaczyłeś po statystykach. ;-)
}
2009-01-14 12:47:03 = Gynvael Coldwind
{
@KKKas
Hehe widziałem, referery na bieżąco śledzę ;> A i w statystykach się to nieźle odbiło - 7 tyś odwiedzin dzisiaj (normalnie mam 50-70 ;D) ;> Cóż.. szczerze nie spodziewałem się ze post o czymś co od roku wisi w formie loga na wyklady.net wzbudzi takie zainteresowanie ;D

Z ciekawostek refererowych, dowiedziałem się że na jutrzejszym kolokwium (?z języków skryptowych?) ma być programowanie obiektowe w .BAT ;> A, no i moje "kotki" są dość popularne hehehe ;> Have fun ;>
}
2009-01-14 13:22:37 = Mike
{
haha :D

bash go zjada na sniadanko z kopytkami :D
}
2009-01-14 17:57:11 = Gynvael Coldwind
{
@Mike
Cóż, trudno zaprzeczyć ;> Ale na tym bym skończył podróż pod tytułem "A jest lepsze od B", nie chcemy przecież flamewar'a ideologicznego, prawda? ;>
}
2009-01-15 00:55:47 = dPeS
{
@Gynvael Coldwind prs chodzilo pewno o takie ,,smaczki'' jak polimorfizm na przyklad ;) i tutaj mial zdecydowanie racje :)
}
2009-01-15 02:20:57 = Gynvael Coldwind
{
@dPeS
Dajmy prs'owi mówić za siebie ;>
Zresztą, na początku arta zaznaczam że to nie jest obiektowość, tylko emulacja obiektowości ;D
}
2009-01-16 00:41:48 = Papa
{
Zajmowałem się .CMD-kami od Windows NT 4.0 jak jeszcze nie było obsługi .VBS-ów i faktycznie dużo się udawało zrealizować korzystając wyłącznie z narzędzi zawartych w pakiecie Windows-a . Nie wiem jak jest teraz z obsługą .BAT-ów, ale kiedyś interpreter traktował je inaczej niż .CMD-ki i obawiam się że powyższe przykłady mogły by nie zadziałać na NT 4 po umieszczeniu w pliku .BAT.
Nie bardzo rozumiem po co robić takie rzeczy jak mamy obiektowe .VBS-y wspierane w Windows-ach począwszy od wersji 2000 ?

Oczywiście to bardzo zacne, że użytkownik Windows zapoznał się dogłębnie z Command Interpreter-em. Znaczy się, że jest to zaawansowany użytkownik :)
}
2009-01-16 02:31:11 = Gynvael Coldwind
{
@Papa
Hmm, nigdy nie zastanawiałem się czy między .BAT a .CMD są jakieś różnice. Kapkę zajrzałem w temat, i wygląda na to że faktycznie mała różnica jest, i polega ona na zmienieniu bądź nie zmienieniu ERRORLEVEL przy niektórych poleceniach.

Dokładne informacje:
http://groups.google.com/group/microsoft.public.win2000.cmdprompt.admin/msg/ad9066638815812c?pli=1

W związku z czym przypuszczam że zmiana rozszerzenia z .BAT na .CMD i w drugą stronę w przypadku powyższego wpisu jest bez znaczenia. I jednocześnie przypuszczam że to wyżej i tak nie ruszy na NT4, z powodu działania praw Murphiego ;> (zdarzyło mi się kilka razy przy robić pewne zmiany w skryptach przy przerzucaniu np z Visty na 2K).

A co do "po co": bo można ;>
Osobiście nie widzę zastosowania do tego, ale w ramach proof of concept postanowiłem i tak to zrobić ;> Do celów praktycznych VBS czy choćby skrypty Monada są oczywiście dużo lepsze ;>
}
2009-01-22 22:32:28 = Marco
{
Mógłby mi ktoś krok po kroku wytłumaczyć jak ten skrypt działa? Thx

@echo off
set h=*
for %%h in (9 1 8 5 7 6 2 3 0) do call :h2 %1 %%h
goto :EOF
:h2
if h%1h==h%2h set h=h
if %h%h==hh goto :%h%
echo %h%*
set h=%h%*
:h
}
2009-01-24 00:37:03 = Gynvael Coldwind
{
@Marco
W przypadku skryptów BAT można stosować bardzo prosty trik ułatwiający debugowanie - usunąć @echo off.
Wtedy przy wykonaniu każdej linii widzisz w jakiej postaci (tzn zmienne są już rozwinięte) się ona wykonuje, i w jakiej kolejności.

W przypadku przedstawionego przez Ciebie skryptu sprawa jest dość prosta ;>
Na początku zmienna h jest równe jednej gwiazdce ;>
Potem jest pętla w której za %%h (nie mylić z %h%) podstawiana w każdym "obrocie" pętli jest jedna z wymienionych liczb (w zasadzie cyfr, ale to mało istotne): 9 1 8 5 7 6 2 3 0. Dla każdej z tej liczb wywoływana jest funkcja :h2 z dwoma parametrami: %1 który jest parametrem skrypty bat oraz %%h, czyli liczby z zestawu.
W zasadzie to są dwa warianty wywołania tej funkcji:
Jeżeli parametr skryptu będzie podany, to h2 będzie wywołane z %1=parametr i %2=%%h
Natomiast jeżeli parametru nie będzie, to %1=%%h, a %2 będzie puste (ponieważ %1 w wywołaniu jest puste, więc bat traktuje to jak powietrze, i myśli że to jest po prostu call<dwie spacje>%%h)

OK, teraz funkcja h2...
Najpierw jest sprawdzenie czy h%1h==h%2h.. w tym przypadku literka 'h' musi występować żeby nie było syntax error w przypadku gdy %1 lub %2 było by puste (to wynika z faktu rozwinięcia zmiennych przed wykonaniem if; jeżeli nie dać tych literek 'h', to przy pustym %1 i %2 wykonane by było if == set h=h, co jest ofc syntax errorem). Anyway, jeżeli parametr skryptu nie jest podany, to ten if będzie zawsze nieprawdziwy. W przeciwnym wypadku zmienna h będzie ustawiona na literke h gdy funkcja będzie wywołana dla liczby z zestawu równej parametrowi skryptu (czyli np jeżeli ktoś odpali a.bat 9, to ten if wykoan się już w pierwszej iteracji).
Drugi if sprawdza czy pierwszy się wykonał, i jeżeli tak to skacze na koniec funkcji.

Dwie przedostatnie linie funkcji to dość prosta sprawa - wypisanie zmiennej h z gwiazdką dodatkową, oraz ustawienie dodanie do zmiennej h kolejnej gwiazdki (set h=%h%).

I tyle. Ktoś bardzo lubi literkę h ;>>>

}
2009-01-24 08:19:48 = Marco
{
Dzięki piękne za pomoc :-)
}
2009-04-16 04:44:59 = Introligator
{
Witam , czy moglby mi ktos pomoc w stworzeniu batcha , ktory sortuje zawartosc plikow *.txt z konkretnego folderu i jego podfolderow?
Ja napisalem cos takiego:

@echo off
cd C:A
dir /B /S *.txt>>C:Ado_posortowania.txt
for /F "tokens=*" %%a in (do_posortowania.txt) do Sort "%%a" /o Posortowane.txt
cls
echo Sorotwanie zakonczone pomyslnie.
pause
exit

ale za bardzo nie dziala ;|
}
2009-04-19 01:15:19 = Gynvael Coldwind
{
@Introligator

sort /o imo wszystko psuje - tj nadpisujesz sobie plik wynikowy co iteracje pętli

Tak na prawdę pojawia się pytanie co chcesz osiągnąć.
Opcje są trzy:

1) chcesz wziąć każdy plik z listy, posortować tylko jego, i nadpisać stary plik nowym posortowanym - czyli sortujesz wszystkie pliki, ale każdy pojedynczo

2) chcesz wczytać wszystkie pliki do jednego miejsca, posortować wszystko razem, i zapisać do osobnego pliku

3) chcesz posortować wszystko oddzielnie, ale wynik zapisać do jednego pliku (takiego sklejonego)

Jeżeli chodzi o 1), to najlepiej to zrobić tak:
@echo off
for /f %%i in ('dir /b /s *.txt') do (
echo Sortuje plik %%i
sort %%i /o posortowane.txt
move /y posortowane.txt %%i > nul
)
echo Koniec!

Jeżeli chodzi o 2), to zrób to tak:
@echo off
del wszystko.txt >nul 2>nul
del posortowane.txt >nul 2>nul
for /f %%i in ('dir /b /s *.txt') do (
echo Wczytuje plik %%i
type %%i >> wszystko.txt
)
echo Sortuje!
sort wszystko.txt /o posortowane.txt
del wszystko.txt >nul 2>nul
echo Koniec!

A jeżeli o 3), to tak:
@echo off
del posortowane.txt >nul 2>nul
for /f %%a in ('dir /b /s *.txt') do (
echo Sortuje %%a
echo %%a >> posortowane.txt
sort %%a >> posortowane.txt
)
echo Koniec!

;>
}
2009-04-20 02:22:19 = Introligator
{
Wielkie dzieki i uklon do pasa. Chodzilo mi o przypadek 2 ale wszystkie 3 czegos mnie naucza. Dziala jak mialo dzialac. Jeszcze raz bardzo dziekuje.
}
2010-03-14 21:35:39 = -=NIKT=-
{
Gratuluję wiedzy
}
2010-03-16 11:15:44 = Gynvael Coldwind
{
@Introligator
:) n/p

@-=NIKT=-
Ehehe dzięki ^^ (chociaż szczerzę, to wiedza o .bat wydaje mi się trochę przeterminowana, z uwagi na pojawienie się powershella etc)
}
2010-04-23 17:57:25 = garsa
{
Poda ktoś download do kompletnego programu, opisanego w artykule?? Był bym wdzięczny...
}
2010-06-02 14:35:58 = wuben
{
Wie ktoś jak wpisać do pliku znak procenta "%"
trzeba znać jego kod ascii ?
}
2010-06-08 23:25:18 = Gynvael Coldwind
{
@garsa
Listing na samym dole postu to kompletny program, a w zasadzie kompletny skrypt.
W zasadzie jedyna rzecz której brakuje, to "setlocal enabledelayedexpansion" po @echo off, tak na wszelki wypadek :)

@wuben
Nie za bardzo rozumiem... mówisz o .bat?
W takim wypadku: echo %% >> plik
}
2010-06-10 16:15:24 = wuben
{
Dzięki Gynvael o to mi chodziło
a jak jest ze znakiem "|"

}
2010-06-15 20:23:51 = Cord
{
Witam
Kawał dobrej roboty:
Ja stworzyłem coś takiego ale przy tym co ty robisz to jakiś potworek

[size=1]Created by opisywarka[/size]

[size=3][color="yellow"]DANE TECHNICZNE[/color][/SIZE]
[CODE]
[/CODE]

[size=3][color="yellow"]OPIS PROBLEMU[/color][/SIZE]
[QUOTE]
@echo off
cls
color 2
echo.
echo ** ****** **
echo /** ** ** **////** /**
echo /** //** ** ** // ****** ****** /**
echo /****** //*** /** **////**//**//* ******
echo /**///** /** /** /** /** /** / **///**
echo /** /** ** //** **/** /** /** /** /**
echo /****** ** //****** //****** /*** //******
echo ///// // ////// ////// /// //////
echo.
echo.
echo Program rysuje prostokat o podanych parametrach
echo.
echo podaj dlugos prostokotu 1-78
echo.
SET /P h=
echo.
echo podaj wysokosc prostokotu 1-48
echo.
SET /P h2=
cls
color 4
set z2=$
set z4=80
set z5=50
set z7=
set /A w1=%z4%-%h%
set /A w1=%w1%/2
set /A w2=%z5%-h2
set /A w2=%w2%/2
:e01
echo.
set /A w2=%w2%-1
if %w2%==0 goto e02
goto e01
:e02
set z6=%z6%%z7%
set /A w1=%w1%-1
if %w1%==0 goto e1
goto e02
:e1
SET /A h=%h%-1
set z3=%z3%%z2%
if %h%==0 goto e2
goto e1
:e2
echo %z6%%z3%
SET /A w=%h2%-1
set h2=%w%
if %w%==0 goto koniec
goto e2
:koniec
ping localhost -n 10 >nul
[/QUOTE]
}
2010-08-15 15:45:55 = wuben
{
Witam wciąż mam problem, nie wiem jak w batchu wpisać do pliku znak separatora "|"

echo || >> plik
nie działa
}
2010-08-15 15:59:06 = Gynvael Coldwind
{
@wuben
Znakiem "ucieczki" w batchu jest caret (czyli ^, zwany również daszkiem ;>)
echo ^| >> plik

Pozdrawiam ;)
}
2010-11-24 21:06:16 = bat-podstawowy
{
Zaciekawił mnie ten ciekawy artykuł parę prostych skryptów już stworzyłem a tu jest ciekawie tylko ze ‘obiektowo w. bat’.
Ten 2 skrypt – kwadrat i trójkąt działa (będę go analizował) tylko ten pierwszy nie mogę uruchomić (xp prof.) może go źle składam? Dodałem setlocal enabledelayedexpansion i tez nic. Mam prośbę o podanie całego skryptu w pliku

setlocal enabledelayedexpansion
call :Plik a ala.txt
:Plik
set %1.name=%2
set %1.read=call :Plik.read %1
goto :EOF
:Plik.read
set j=0
for /f "delims=" %%i in ('type !%1.name!') do (
set %1.lines.!j!=%%i
set /a j=!j!+1
)
set %1.count=%j%
goto :EOF
%a.read%
echo Ilosc linii : %a.count%
echo Druga linia : %a.lines.1%
echo Trzecia linia: %a.lines.2%
goto :EOF
}
2010-11-24 23:39:48 = Gynvael Coldwind
{
@bat-podstawowy
Postaram się rzucić jutro okiem czy ten skrypt działa na XP. Z tego co pamiętam testowałem je na Viście.
}
2011-01-20 13:14:43 = Paul
{
Czy można napisać skrypt bat, który zamieni znaki z polskimi ogonkami, wprowadzoną przez użytkownika np. imię, tak żeby w innej zmiennej uzyskać ciąg znaków pozbawionych polskich znaków ?
Np. użytkownik wprowadza "Jaś_Wąż" a skrypt podstawia pod zmienną n_no_pl ciąg "Jas_Waz"?
}
2011-05-16 06:31:31 = Gregis
{
Pełen SZACUN - świetnie opisany przykład, normalnie REWELKA !
}
2011-12-27 16:42:51 = anonymous
{
Mam pytanie. Czy w batch'u da się jakoś odczytywać dane ze stron internetowych? Chodzi mi o to, że na jakiejś stronie napisanej w html byłoby np. "version=2.0" a program odczytywałby na stronie jaka jest najnowsza wersja programu i wyświetlał ją użytkownikowi. Z góry dzięki.
}
2012-05-23 21:36:41 = bla
{
Twój skrypt coś mi przypomina...

#/bin/bash
#Sets gamma and runs UrbanTerror

xgamma -gamma 2
./ioUrbanTerror.x86_64
xgamma -gamma 1
}
2012-09-14 19:19:31 = GOKOP
{
Ostatni przykład nie działa :c (Win Vista)
}
2013-11-23 00:49:33 = AdamKowalsky
{
Siema. Mam kilka problemów.
Chce napisać taki skrypt.
1. otwieram plik, mam ciąg danych, chce wczytać pierwsze 6 znaków.
2. użyć tych znaków w jakimś poleceniu(to wiem jak zrobić)
3.zapisać wynik tego polecenia w txt
4. zapętlić i znów wczytać 6 znaków ale z pominięciem pierwszych 6, znaki są napisane jednym ciągiem.

teraz moje pytania.
1. Jak wczytać konkretną ilość znaków i jak ustawić od którego miejsca mają być wczytane dane(to się chyba offset profesjonalnie nazywa)
2. czy jak chce zapisać dane do drugiego pliku txt to pierwszy musi być zamknięty?

chce to uruchomić w cmd
ps. mam coś kombinować z copy czy jest do tego jakaś inna funkcja?

Dziękuje,
pozdrawiam
}
2013-11-23 19:29:45 = Gynvael Coldwind
{
@AdamKowalsky
Hey,

Ad 1.
Hmmm, sam BAT ma kiepską obsługę wyciągania danych z pliku, natomiast jakieś narzędzia z coreutils (http://gnuwin32.sourceforge.net/packages/coreutils.htm) mogą w tym pomóc, np. połączenie head z tail, albo lepiej - dd.

Ad 2.
Nie, nie musi.

Cheers,
}
2016-07-16 07:46:08 = Eap
{
ja robie sytem operacyjny w .bat :O
}
2019-05-08 05:57:32 = jaco0l
{
Czy wie ktoś jak napisać .bat do zmiany języka wyświetlanie Windows 10?
}
2020-04-22 13:14:16 = mandzio
{
Wie ktoś jak napisać plik wsadowy który pauzuje się po naciśnięciu danego przycisku?
}

Add a comment:

Nick:
URL (optional):
Math captcha: 7 ∗ 4 + 4 =