Dyskietka startowa MS-DOS
[ AUTOEXEC.BAT - WIELK. 95 B - plik konfiguracyjny i ładujący system DOS;
[ COMMAND.COM - WIELK. 93010 B - interpreter poleceń (zapewnia komunikację z systemem);
[ CONFIG.SYS - WIELK. 33 B - plik konfiguracyjny środowiska DOS;
[ DISPLAY.SYS - WIELK. 17 175 B - sterownik ekranu;
[ EGA.CPI - WIELK. 58 870 B - strona kodowa;
[ IO.SYS - WIELK. 116 736 B - jądro systemu DOS;
[ KEYB.COM - WIELK. 21 607 B - program obsługi klawiatury;
[ KEYBOARD.SYS - WIELK. 34 566 B - sterownik klawiatury;
[ KEYBRD4.SYS - WIELK. 13014 B - sterownik klawiatury polskiej;
[ MODE.COM - WIELK. 29 239 B;
[ MSDOS.SYS - WIELK. 9 B - zarządzanie pamięcią, systemem plików i procesami;
Pliki wsadowe systemu MS-DOS
Po wydaniu dowolnego polecenia interpreter command.com sprawdza w pierwszej kolejności
czy wydana komenda jest poleceniem wewnętrznym (interpretowanym przez command.com) i
w przypadku odpowiedzi pozytywnej wykonuje wydaną komendę. Jeżeli jednak interpreter nie
rozpoznaje polecenia to przyjmuje, że użytkownik zarządał uruchomienia programu.
Dla przykładu przyjmijmy, że wpisano komendę
sleep 10
Command.com poszukuje wówczas pliku o nazwie o nazwie sleep.com, następnie pliku sleep.exe i ostecznie pliku sleep.bat. Po znalezieniu jednego z dwóch pierwszych zbiorów command.com uruchamia znaleziony program, w przypadku znalezienia zbioru bat wykonuje jego interpretację.
Plik wsadowy, aby mógł być poprawnie wykonany (zinterpretowany) powinien zawierać ciąg
poleceń systemu, z których każde powinno być umieszczone w osobnej linii pliku. Mogą to
być polecenia wewnetrzne, polecenia zewnętrzne (programy) lub polecenia specyficzne dla
pliku wsadowego (polecenia, które są dozwolone tylko w tym pliku).
Oto prosty przykład pliku wsadowego:
REM Plik Info.bat ECHO Konfiguracja systemu MS-DOS ECHO [autoexec.bat] TYPE C:\autoexec.bat | MORE ECHO [config.sys] TYPE C:\config.sys | MORE ECHO [Dysk twardy C:] LABEL ECHO Naciśnij jakiś klawisz... PAUSE
Aby wykonać powyższy plik należy nadać mu nazwę z rozszerzeniem bat (może być Info.bat) a następnie w katalogu bieżącym wpisać komendę będącą nazwą pliku wsadowego, czyli odpowiednio:
C:\TEMP>info
Interpreter wykonuje sekwencyjnie jedno po drugim wszystkie polecenia pliku wsadowego w kolejności ich występowania. Pierwsza linia pliku (polecenie REM) jest komentarzem jest komentarzem i podczas wykonywania nie jest brana pod uwagę. Dwie kolejne linie zawierają polecenie ECHO, którego wykonanie polega na wypisaniu podanego tekstu na ekranie. Linie 4 i 6 zawierają polecenie MS-DOS wypisania na ekranie podanych plików (TYPE) z podziałem na strony (MORE). Linia ostatnia zawiera polecenie PAUSE, którego wykonanie polega na wypisaniu tekstu "Naciśnij jakiś klawisz, aby kontynuować..." i zatrzymaniu wykonywania pliku wsadowego do czasu naciśnięcia dowolnego klawisza.
Polecenie ECHO
Jeżeli wykonamy plik wsadowy test.bat zawierający tylko jedną linię z komendą
DIR, to na ekranie zostaną wypisane dwie rzeczy:
C:\BATCH>test C:\BATCH>dir Wolumin w stacji dysków C nie ma etykiety Numer seryjny woluminu: 364F-10E8 Katalog C:\BATCH . <DIR> 00.08.04 20:42 . .. <DIR> 00.08.04 20:42 .. TEST BAT 3 00.08.04 20:43 test.bat 1 plik(ów) 3 bajtów 2 katalog(ów) 271 859 712 bajtów wolnych C:\BATCH>_
Pierwsza linia zawiera tekst wydanej komendy. W linii drugiej interpreter wypisał treść polecenia występującego w pliku wsadowym. Kolejne linie zawierają wynik wykonanania polecenia DIR. Przykład ten pokazuje sposób postępowania podczas wykonywania pliku wsadowego - command.com czyta linię pliku wsadowego, wypisuje ją na ekranie a następnie uruchamia odpowiedni program lub polecenie wewnętrzne. Po zakończeniu wykonywania polecenia proces się powtarza - odczyta kolejną linię, wypisze jej treść na ekranie a następnie uruchomi odpowiedni program, itd.
Polecenie ECHO można wydać z argumentem ON lub OFF. Instrukcja
ECHO OFF
powoduje wyłączenie wypisywania treści poleceń występujących w pliku wsadowym. Od momentu
wykonania tej instrukcji command.com nie będzie wypisywał treści przetwarzanych
komend a jedynie ich wyniki. Bardzo często instrukcję powyższą umieszcza się w
pierwszej linii pliku wsadowego.
Użycie argumentu ON powoduje oczywiście włączenie wypisywania treści poleceń.
Z analizy wydruku dowolnego pliku wsadowego zawierającego w pierwszej linii komendę ECHO OFF można wywnioskować, że wyłączone tą komendą wypisywanie treści poleceń obowiązuje dopiero od linii drugiej - command.com zawsze wypisze treść pierwszej komendy pliku, czyli ECHO OFF. Aby tego uniknąć należy linię tą poprzedzić znakiem '@' ("at") - linia pliku, która poprzedzona jest tym znakiem nigdy nie jest wyświetlana na ekranie.
Podsumowując: istnieją dwie metody całkowitego wyłączenia wypisywania treści komend pliku wsadowego:
IF EXIST plik komenda albo IF NOT EXIST plik komenda
Instrukcja w tej postaci pozwala na wykonananie dowolnego polecenia tylko wówczas, gdy istnieje podany plik (lub gdy nie istnieje jeśli użyto NOT). Rozważmy dwie następujące komendy:
[1] DEL lista.txt > NUL [2] IF EXIST lista.txt DEL lista.txt > NUL
Polecenie [1] jest oczywiste: usuń plik lista.txt. Polecenie [2] mówi: jeżeli istnieje plik lista.txt, to usuń ten plik. Efekt końcowy obu poleceń jest taki sam - zostanie usunięty plik lista.txt. Pomiędzy tymi poleceniami istnieje jednak pewna różnica; o poleceniu [2] można by powiedzieć, że "jest lepsze". Otóż polecenie DEL usuwa podany plik i nie wyświetla żadnych komunikatów o usunięciu pliku, jeżeli jednak usuwany plik nie istnieje, to wykonanie polecenia jest niemożliwe - zostanie wówczas wyświetlony komunikat o błędzie - mimo przekierowania wyjścia polecenia do pliku pustego komunikat ów pojawi się na ekranie. Taka sytuacja nie będzie miała miejsca w przypadku polecenia [2]: to polecenie bowiem wykona komendę DEL lista.txt tylko wówczas, gdy plik lista.txt istnieje - jeżeli w katalogu bieżącym pliku nie ma, to komenda jest pomijana i na tym kończy się wykonanie całej instrukcji warunkowej.
Polecenie DEL można tutaj zastąpić inną komendą, np:
[1] TYPE lista.txt [2] IF EXIST lista.txt TYPE lista.txt
W tym wypadku mamy doczynienia z tą samą sytuacją: jeżeli nie istnieje plik lista.txt, to polecenie [1] wypisze komunikat o błędzie - nie zrobi tego natomiast polecenie [2].
Etykiety i instrukcja skoku GOTO
Rozważymy przkład trochę trudniejszy. Należy utworzyć kopię pliku lista.txt pod
nazwą lista.bak. Tutaj również wskazane jest wykorzystanie instrukcji warunkowej:
@ECHO OFF IF EXIST lista.txt COPY lista.txt lista.bak > NUL
Jeżeli w katalogu bieżącym istnieje plik lista.txt zostanie wykonane polecenie
utworzenia jego kopii pod nazwą lista.bak.
Konstruując powyższy plik należy przewidzieć jeszcze jedną sytuację: w katalogu bieżącym
może również istnieć plik o nazwie lista.bak. Powstaje wówczas pytanie "co w tej
sytuacji zrobi polecenie COPY?" - albo wyświetli komunikat o błędzie i nie wykona
kopiowania, albo też skopiuje plik Ľródłowy usuwając przy tym zawartość istniejącego
pliku docelowego - w pewnych sytuacjach obie z tych możliwości mogą okazać się
niezadawalające.
Istnieją oczywiście metody rozwiązania tego problemu za pomocą opcji polecenia COPY,
warto jednak pamiętać, że opcje poleceń często zmieniają się w różnych wersjach interpretera
command.com i komenda, która poprawnie wykonuje się na naszym komputerze może w innej
wersji interpretera zostać uznana za niepoprawną z powodu błędnej opcji polecenia.
Powyższy przykład demonstruje problem wykonania komendy tylko wówczas, gdy spełnione są dwa lub więcej określonych warunków - problemy tego typu rozwiązuje się na ogół za pomocą instrukcji skoku GOTO.
Instrukcja:
:Etykieta
definiuje tzw. etykietę w pliku wsadowym. Etykieta to inaczej mówiąc słowna nazwa
linii pliku, umieszczając instrukcję etykiety nazywamy linię pliku podaną po znaku ':'
nazwą. Nazwa etykiety powinna być jednym słowem nie zawierającym odstępów (można połaczyć
słowa znakiem '_') i powinna rozpoczynać się tuż za znakiem ':', nie należy rozdzielać
nazwy i znaku ':' odstępami.
Podczas wykonywania pliku wsadowego interpreter pomija linie pliku zawierające etykiety
(podobnie jak ma ty miejsce w przypadku polecenia komentarza REM), instrukcji tej
nie wykonuje się, służy ona jedynie do przenoszenia wykonywania pliku przez instrukcję
skoku GOTO:
GOTO Etykieta
Wykonanie instrukcji skoku polega na przeniesieniu wykonywania pliku do tej linii w pliku, która zawiera (jest nazwana) podaną etykietę (wpisujemy tutaj tylko nazwę etykiety, bez znaku ':').
Wróćmy teraz do przykładu usuwania pliku:
[1] @ECHO OFF [2] IF EXIST lista.txt GOTO Usuwaj [3] ECHO Nie ma takiego pliku... [4] GOTO Koniec [5] :Usuwaj [6] ECHO Usuwanie pliku lista.txt... [7] DEL lista.txt > NUL [8] ECHO Wykonane... [9] :Koniec
W linii [2] następuje sprawdzenie istnienia w katalogu bieżącym pliku lista.txt.
Jeżeli plik istnieje wykonana zostanie komenda GOTO Usuwaj - nastąpi przejście
(przeniesienie wykonywania) do linii oznaczonej etykietą Usuwaj, czyli do linii [5].
Linia ta zostanie zignorowana przez command.com, który rozpocznie wykonywanie
pliku od linii następnej [6]. Wypisany zostanie tekst "Usuwanie pliku lista.txt...", następnie
interpreter wykona linię [7] usuwając plik lista.txt, wypisze tekst "Wykonane..." i
zakończy wykonywanie pliku na ostatniej linii [9].
Podczas wykonywania linii [2] może się oczywiście okazać, że katalog bieżący nie zawiera pliku
lista.txt. Instrukcja warunkowa wówczas pominie podaną komendę GOTO Usuwaj i
wykonana zostanie komenda następna w linii [3] - wypisanie tekstu "Nie ma takiego pliku..."
oraz komenda w linii [4] - przejście do etykiety Koniec.
Warto jeszcze zwrócić uwagę na linię [4]. Brak tej linii spowodowałby wypisanie tekstu
"Nie ma takiego pliku..." a następnie wykonanie komendy w liniach [6], [7] i [8], czyli
pomimo nieistnienia pliku byłyby wykonywane polecenia związane z jego usunięciem.
Plik wsadowy wykonujący wspomniane wcześniej kopiowanie pliku lista.txt na lista.bak mógłby mieć postać:
@ECHO OFF IF NOT EXIST lista.txt GOTO BrakPliku IF EXIST lista.bak GOTO IstniejeKopia ECHO Kopiowanie lista.txt na lista.bak... COPY lista.txt lista.bak > NUL ECHO Wykonane... GOTO Koniec :BrakPliku ECHO Plik lista.txt nie istnieje... GOTO Koniec :IstniejeKopia ECHO Plik lista.bak już istnieje... :Koniec
@ECHO OFF IF EXIST %1 GOTO Usuwaj ECHO Plik %1 nie istnieje... GOTO Koniec :Usuwaj ECHO Usuwanie pliku %1 ... DEL %1 > NUL ECHO Wykonane... :Koniec
UWAGA: plik należy uruchomić z argumentem będącym nazwą pliku -
jego brak może spowodować błąd wykonania i w konsekwencji komunikat o wymaganym argumencie.
Interpreter podczas analizy linii pliku wszystkie wyrażenia postaci %1, %2, ..., %9
zastępuje faktycznymi argumentami podanymi w linii komend:
C:\TEMP>mydel.bat lista.txt Usuwanie pliku lista.txt ... Wykonane... C:\TEMP>_
Widać powyżej, że w linii drugiej interpreter zamiast symbolu %1 wypisał faktycznie
podany argument w wywołaniu lista.txt.
Jeżeli plik wsadowy uruchamiamy bez argumentów to wszystkie wyrażenia %1, %2, ..., %9
są napisami pustymi (napis nie zawierający żadnych znaków). Jeżeli w linii
komend występuje N argumentów, to wyrażenia %1, ..., %N reprezentują podane argumenty,
wyrażenia %N+1, %N+2, ... są natomist napisami pustymi.
Nasuwa się proste pytanie, czy plik wsadowy można przetworzyć z dziesięcioma lub więcej
argumentami. OdpowiedĽ w zasadzie jest twierdząca, ale o tym nieco póĽniej...
Instrukcja warunkowa (2)
Druga postać instrukcji warunkowej dotyczy porównywania napisów:
IF "napis1" == "napis2" komenda albo IF NOT "napis1" == "napis2" komenda
Instrukcja w tej postaci powoduje wykonanie podanej komendy tylko wówczas, gdy oba napisy napis1 i napis2 są równe, czyli takie same. Słowo równość oznacza tutaj równość idealną - napisy musza mieć taką samą długość i składać się z takich samych znaków. W przypadku nazw plików i katalogów duże i małe litery nie są rozróżnialne, w przypadku porównywania napisów brane jest to pod uwagę. Tak więc napisy "Lista.txt" oraz "lista.txt" wcale nie są równe.
Warto pamiętać, że bezpieczniej jest podawać porównywane napisy w cudzysłowie oraz pomiędzy napisami a znakiem '=' umieścić znak odstępu - jego brak może spowodować błąd wykonania pliku.
Ta postać instrukcji warunkowej posłuży nam przede wszystkim do sprawdzania ilości podanych argumentów. Korzystając o obu postaci instrukcji możemy napisać ostateczną wersję pliku wsadowego mydel.bat usuwającego plik podany jako argument, przyjmując przy tym następujące założenia:
@ECHO OFF REM REM Usuwa plik podany jako argument REM IF "%1" == "/?" GOTO Informacja IF "%1" == "" GOTO BrakArgumentu IF NOT "%2" == "" GOTO ZbytWieleArgumentow IF EXIST %1 GOTO Usuwaj ECHO Plik [%1] nie istnieje. GOTO Koniec :Usuwaj ECHO Usuwanie [%1] DEL %1 > NUL GOTO Koniec :BrakArgumentu ECHO Oczekiwany argument. GOTO Skladnia :ZbytWieleArgumentow ECHO Zbyt wiele argumentów. GOTO Skladnia :Informacja ECHO Usuwa podany plik. :Skladnia ECHO Składnia polecenia: ECHO MYDEL [/?] nazwa_pliku :Koniec
Mimo iż czynność jest stosunkowo prosta, to konstrukcja pliku wymaga sporego nakładu
pracy. Przeanalizujemy krótko poszczególne warunki zadania.
Z przyjętych założeń wynika, że dopuszczalne są wywołania: "mydel /?", "mydel /? /?",
"mydel /? lista.txt", "mydel /? lista.txt lista.bak" - dopuszczalne jest każde wywołanie,
w którym pierwszy argument jest równy "/?". W związku z tym w pliku wsadowym w pierwszej
kolejności sprawdzamy wystąpienie tego właśnie argumentu.
Kolejne instrukcje warunkowe dotyczą już przypadków uruchomienia bez argumentów lub
z argumentami, ale z pierwszym argumentem różnym od "/?". Sprawdzamy najpierw czy podano
jakikolwiek argument.
Trzecia istrukcja IF dotyczy przypadku: podano co najmniej jeden argument i argument
pierwszy jest nazwą pliku. Wówczas usuwamy plik jeżeli jest to jedyny argument lub wypisujemy
komunikat o błędzie gdy podano więcej niż jedną nazwę pliku. Ilość podanych argumentów, a
właściwie to czy argument jest jeden, sprawdzamy porównując argument drugi %2 z
napisem pustym.
Ostatnie IF dotyczy już tylko przypadku: podano dokładnie jeden argument będący nazwą
pliku - pozostaje więc sprawdzić czy podany plik istnieje.
Instrukcja CALL
Jak wspomniano na początku w pliku wsadowym można używać dowolnych poleceń wewnetrznych
i programów wykonywalnych (com i exe). Polecenie pliku wsadowego nie może
natomiast być plikiem wsadowym. Uruchomienie w pliku wsadowym innego pliku wsadowego
wymaga zastosowania polecenia:
CALL plik_wsadowy [argumenty]
Do tej pory stosowane były instrukcje skoku zawsze do etykiety położonej "poniżej" w
pliku wsadowym. Istnieje możliwość przeniesienia wykonywania pliku do linii wcześniejszej,
czyli "powyżej" - tego typu konstrukcję, tzn. etykietę oraz występującą poniżej instrukcję
skoku do tej właśnie etykiety nazywamy pętlą.
Pętle często stosuje się w połączeniu z instrukcją SHIFT. Polecenie SHIFT
wykonuje tzw. przesunięcie argumentów, tzn. argument pierwszy %1 zastępowany jest
przez argument drugi %2, argument drugi %2 zastępowany jest przez argument trzeci %3, itd.
Ogólnie: argument %N zastępowany jest przez argument %(N+1).
UWAGA:
W wyniku wykonania polecenia argument pierwszy pliku wsadowego jest
bezpowrotnie tracony - nie ma możliwości odwołania się do tego argumentu. Demonstruje
to poniższy przykład:
@ECHO OFF ECHO Arg1=[%1] Arg2=[%2] Arg3=[%3] Arg4=[%4] SHIFT ECHO Arg1=[%1] Arg2=[%2] Arg3=[%3] Arg4=[%4] SHIFT ECHO Arg1=[%1] Arg2=[%2] Arg3=[%3] Arg4=[%4] SHIFT ECHO Arg1=[%1] Arg2=[%2] Arg3=[%3] Arg4=[%4] SHIFT ECHO Arg1=[%1] Arg2=[%2] Arg3=[%3] Arg4=[%4] SHIFT ECHO Arg1=[%1] Arg2=[%2] Arg3=[%3] Arg4=[%4]
Tak wygląda wykonanie pliku z pięcioma argumentami:
C:\TEMP>argumen.bat list1.txt list2.txt list3.txt list4.txt list5.txt Arg1=[list1.txt] Arg2=[list2.txt] Arg3=[list3.txt] Arg4=[list4.txt] Arg1=[list2.txt] Arg2=[list3.txt] Arg3=[list4.txt] Arg4=[list5.txt] Arg1=[list3.txt] Arg2=[list4.txt] Arg3=[list5.txt] Arg4=[] Arg1=[list4.txt] Arg2=[list5.txt] Arg3=[] Arg4=[] Arg1=[list5.txt] Arg2=[] Arg3=[] Arg4=[] Arg1=[] Arg2=[] Arg3=[] Arg4=[]
Po pierwszym wykonaniu polecenia SHIFT wyrażenie %1 reprezentuje już
napis list2.txt, wyrażenie %2 napis list3.txt i tak dalej.
Po wykonaniu drugim wyrażenie %1 jest równe list3.txt, zaś %4
jest w ogóle napisem pustym - %4 musiałoby reprezentować szósty argument podany
w wywołaniu, tymczasem podano tylko pięć argumentów.
Po piątym wywołaniu wszystkie argumenty mają wartość pustą!. Ogólnie: jeżeli plik
wsadowy uruchomiony został z N argumentami, to po N-1 wykonaniu instrukcji SHIFT
ostatni z podanych argumentów znajduje się na miejscu %1, po wykonaniu N-tym
plik wsadowy w ogóle nie ma argumentów.
Oto prosty przykład pliku wsadowego argument.bat, który umieszcza w pliku o nazwie argument.txt wszystkie podane argumenty, każdy w osobnej linii.
@ECHO OFF IF "%1" == "/?" GOTO Informacja :Start IF "%1" == "" GOTO Koniec ECHO %1 >> argument.txt SHIFT GOTO Start :Informacja ECHO Umieszcza w pliku argument.txt wszystkie podane argumenty. ECHO Składnia polecenia: ECHO ARGUMENT [/?] [arg1 arg2 ...] :Koniec
Jeśli pierwszy argument jest równy "/?" zostanie wyświetlona pomoc. W pozostałych przypadkach
wykonywana jest pętla od etykiety Start do instrukcji skoku GOTO Start.
Najważniejszą instrukcją każdej pętli jest instrukcja przerwania pętli, czyli przeniesienia
wykonywania pliku poza pętlę. W tym wypadku zadanie to wykonuje polecenie IF, które
sprawdza niepustość argumentu %1. Cały cykl powtarzany jest tak długo aż argument
%1 osiągnie wartość napisu pustego. Ponieważ wewnątrz pętli występuje polecenie
SHIFT w którymś momencie skończą się argumenty pliku i wykonywanie pętli zostanie
zakończone.
Konstruując pętlę należy zawsze stworzyć warunki umożliwiające jej zakończenie. Nietrudno
przewidzieć jaki efekt można osiągnąć po usunięciu z powyższego pliku instrukcji SHIFT.
Wówczas podczas wykonywania pętli argumenty nie ulegałyby żadnym zmianom co oznacza, że pętla
mogłaby się nigdy nie skończyć. Ten sam skutek przyniosłoby usunięcie instrukcji wyjścia
z pętli IF. W tym wypadku argumenty do ich wyczerpania ulegałyby zmianom, nie wpłynęłoby
to jednak na instrukcję GOTO Start, która zawsze wykonywałaby skok do podanej etykiety.
Taką sytuację nazywamy często "zapętleniem lub powieszeniem programu".
Jeżeli używamy w pliku wsadowym pętli wskazane jest przedsięwzięcie pewnych środków ostrożności. Otóż wykonanie pliku wsadowego można przerwać naciskając klawisz Ctrl+C. Wówczas command.com może zareagować na naciśnięty klawisz i zakończyć wykonywanie pliku, aby jednak było to możliwe należy ustawić wykrywalność tego klawisza poleceniem:
BREAK ON
Polecenie to można wydać na klawiaturze, albo umieścić w pliku wsadowym przed rozpoczęciem
pętli - najlepiej na początku pliku. Samo polecenie BREAK bez argumentu ON lub OFF
wyświetla jedynie stan reakcji na klawisz Ctrl+C.
Warto pamiętać:
NIEOMYLNOŚĆ = FORMAT C:
co mniej więcej znaczy tyle, że kres wiary we własne umiejętności zawsze idzie w parze z utratą części dysku.
Pętle wykorzystujemy na ogół, gdy określoną czynność trzeba wykonać na większej liczbie liczbie plików. Mając do dyspozycji plik wsadowy mydel.bat usuwający jeden podany plik, zadanie polegające na usunięciu wszystkich plików będących argumentami pliku wsadowego sprowadza się wyłącznie do wywołania pliku mydel.bat taką ilość razy, ile plików mamy usunąć.
Przykład:
Napisać plik wsadowy usuwający wszystkie pliku podane w postaci argumentów.
@ECHO OFF BREAK ON :Start IF "%1" == "" GOTO Koniec CALL mydel.bat %1 SHIFT GOTO Start :Koniec
Obsługę błędów oraz "pomoc" należy dopisać samodzielnie.
Instrukcja warunkowa (3)
I to chyba jest ten moment, który nazwać można "wyższą szkołą jazdy"...
Ale najpierw trochę niezbędnej teorii.
Kiedy program kończy swoje działanie ma możliwość poinformowania systemu operacyjnego
o stanie swojego zakończenia. Przekazana informacja jest dosyć uboga albowiem może
być zaledwie nieujemną liczbą całkowitą, ale o tym, że w świecie komputerów jedna liczba
może być informacją bardzo obszerną nikogo przekonywać nie trzeba. Liczbę tą nazywamy
kodem wyjścia programu.
Z możliwości tej programy nie zawsze korzystają i często program nie pozostawia po sobie
żadnej informacji - wówczas system operacyjny traktuje taki stan zakończenia jako poprawny
i przyjmuje, że zakończony program pozostawił po sobie kod zero (często mówimy też,
że program zakończył się z kodem zero). Nie oznacza to wcale, że liczby różne od zera
oznaczają błędne zakończenie programu; jest to często przyjmowana w informatyce reguła
na mocy której liczba zero oznacza poprawne wykonanie określonej operacji.
Instrukcja warunkowa w trzeciej postaci służy właśnie do sprawdzania stanu zakończenia ostatnio wykonanego programu lub komendy:
IF ERRORLEVEL kod_wyjścia komenda albo IF NOT ERRORLEVEL kod_wyjścia komenda
Kod_wyjścia jest tutaj liczbą naturalną, komenda poleceniem do wykonania.
Instrukcja w tej postaci wykona podaną komendę tylko wówczas, gdy ostatnio wykonywane
polecenie zwróciło kod wyjścia większy lub równy podanej liczbie (w przypadku użycia
NOT mniejszy od podanej liczby).
Z tej postaci instrukcji warunkowej korzystać będziemy wyłącznie przy sprawdzaniu kodu
wyjścia polecenia CHOICE, które stosuje się w systemie MS-DOS do zadawania
różnego rodzaju pytań. Składnia polecenia jest następująca:
CHOICE [/C:odpowiedzi] [/N] [/T:Z,XY] [tekst]
Co robi polecenie CHOICE? Po wydaniu komendy CHOICE bez argumentów na ekranie
zostanie wyświetlony napis "[T,N]?" a następnie program będzie czekał do momentu naciśnięcia
jednej z liter 'T' lub 'N'. Wydanie polecenia w postaci CHOICE /C:12A* spowoduje
wypisanie tekstu "[1,2,A,*]?" i oczekiwanie programu na naciśnięcie któregoś z podanych znaków.
Jeżeli podamy określony tekst, to program wypisze go a następnie wyświetli listę dopuszczalnych
odpowiedzi. Użycie opcji "/N" spowoduje, że nie zostanie wyświetlona lista odpowiedzi, opcja
"/T" określa odpowiedĽ domyślną Z po XY sekundach.
Po wydaniu polecenia:
CHOICE /C:ABX /N /T:0,5 "Rodzaj szkoły? [A-podst, B-średn, X-żadna] : "
na ekranie pojawi się tekst "Rodzaj szkoły? [A-podst, B-średn, X-żadna] : " a następnie
program będzie czekał na naciśnięcie jednego z klawiszy A, B, X przez maksymalnie 5 sekund -
niewybranie żadnej z odpowiedzi jest równoznaczne z wybraniem odpowiedzi domyślnej, czyli
odpowiedzi X.
Program po wyborze odpowiedniego klawisza bądĽ po upływie dopuszczalnego czasu kończy swoje
działanie zwracając do systemu operacyjnego kod wyjścia, który jest numerem odpowiedzi na
podanej liście, tzn. po wyborze A program zwróci 1, po wyborze B liczbę 2, zaś po wyborze
X liczbę 3.
Przykład:
Napisać plik wsadowy, który będzie potrafił uruchomić jeden z trzech programów w zależności
od wyboru użytkownika, np. Norton Commander lub Windows.
@ECHO OFF :Start CLS ECHO _ ECHO _ ECHO [ 1 ]. Norton Commander ECHO [ 2 ]. Turbo Pascal ECHO [ 3 ]. Windows ECHO [ Q ]. Zakończ ECHO _ ECHO _ CHOICE /C:123Q /N "Wybierz program do uruchomienia : " IF ERRORLEVEL 4 GOTO Koniec IF ERRORLEVEL 3 GOTO Windows IF ERRORLEVEL 2 GOTO Pascal ECHO Trwa uruchamianie Norton Commandera... C:\NC\NC.EXE GOTO Start :Windows ECHO Trwa uruchamianie systemu Windows... C:\WINDOWS\WIN.COM GOTO Koniec :Pascal ECHO Trwa uruchamianie Turbo Pascala... C:\TP7\TURBO.EXE GOTO Start :Koniec
Linie zawierające polecenie ECHO z kreską podkreślenia należy wpisać w następujący
sposób: po wpisaniu słowa ECHO należy wpisać klawisz spacji a następnie nacisnąć i
przytrzymać klawisz Alt i przy wciśniętym klawiszu Alt na klawiaturze
numerycznej (z prawej strony) wpisać kod znaku 255 po czym można zwolnić klawisz Alt
- kursor powinien się wówczas przesunąć o jedną pozycję w lewo, a wszystko to po to, aby
zmusić polecenie ECHO do wypisania pustej linii.
Podane w pliku ściezki dostępu muszą oczywiście być poprawne - można je nawet zmienić na
ścieżki do innych programów.
Zwrócmy uwagę na kolejność sprawdzania kodu wyjścia polecenia CHOICE. Instrukcje
warunkowe porównują kod wyjścia od wartości największej możliwej czyli 4 w dół do wartości
przedostatniej 2 - pominięcie wszystkich IF jest równoważne z wyborem odpowiedzi
pierwszej. Taki sposób sprawdzania wartości kodu jest konsekwencją sposobu wykonywania
instrukcji warunkowej - jeżeli w pierwszej instrukcji IF umieścilibyśmy kod 2, to
spełnienie tego warunku mówiłoby tylko tyle, że wybrano odpowiedĽ 2, 3 lub 4. Można
przyjąć, że sprawdzanie kodu wyjścia zawsze wykonujemy w ten sam sposób od wartości
największych do najmniejszych - choć oczywiście można wykonać to inaczej.
Pozostaje tylko dodać, że uruchomienia systemu Windows podczas pracy Windows
jest raczej niewykonalne i zakończy się odpowiednim komunikatem. Można to jednak zrobić
podczas pracy trybu MS-DOS (tryb MS-DOS jest czymś innym niż
Wiersz poleceń). Kto zamierza to sprawdzić, powinien odnaleĽć plik
C:\autoexec.bat i w ostatnim wierszu tego pliku wpisać polecenie uruchamiające
powyższy plik wsadowy, czyli np. CALL C:\TEMP\mymenu.bat, po czym wykonać
"reboot" komputera.
Przykład:
Jako drugi przykład wykorzystania trzeciej postaci instrukcji warunkowej napiszemy plik
wsadowy zmieniający nazwę pliku. Obsługę błędów oraz informacje o przeznaczeniu należy
uzupełnić samodzielnie.
@ECHO OFF BREAK ON :Usuwaj IF NOT EXIST %2 GOTO MoznaZmienic CHOICE /C:TN "Plik %2 już istnieje. Usunąć istniejący plik " IF ERRORLEVEL 2 GOTO Koniec DEL %2 > NUL :MoznaZmienic ECHO Przenoszenie %1 na %2 REN %1 %2 > NUL GOTO Koniec :Koniec
Przejście do etykiety Usuwaj powinno nastąpić w sytuacji gdy podano dwa argumenty będące nazwami plików i argument pierwszy jest nazwą istniejącego pliku. Wówczas jeżeli nie istnieje plik podany jako drugi argument, to zmieniamy nazwę pliku, w przeciwnym wypadku zadajemy pytanie czy usunąć istniejący plik. Po odpowiedzi negatywnej przechodzimy na koniec pliku wsadowego, w przypadku odpowiedzi pozytywnej usuwamy istniejący plik i wykonujemy zmianę nazwy.
Instrukcja iteracyjna FOR
Instrukcje iteracyjne (powtarzające, zwane też pętlami) służą w językach
programowania do wielokkrotnego wykonywania podobnych czynności. Ogólnie dzieli się instrukcje
iteracyjne na pętle o znanej lub niemożliwej do przewidzenia z góry liczbie powtórzeń.
Sformułowanie "o znanej liczbie powtórzeń" wymaga pewnego wyjaśnienia. Przez znaną ilość
iteracji rozumie się tu ilość znaną nie w momencie pisania programu lub pliku wsadowego, tylko
ilość znaną w momencie rozpoczęcia wykonywania pętli. I tak na przykład: jeżeli pętla zostanie
powtórzona tyle razy ile plików zawiera katalog bieżący, to mimo iż nie możemy przewidzieć
ile plików będzie zawierał katalog traktujemy tą pętlę jako pętlę o znanej liczbie powtórzeń -
liczba tą będzie bowiem znana w momencie rozpoczynania pętli. Również omówiony wcześniej
przykład pliku wsadowego, który usuwał wszystkie pliki podane jako argumenty jest przykładem
pętli o znanej liczbie powtórzeń - plik można uruchomić z każdą liczbą argumentów, niemniej
jednak liczba ta zawsze jest znana w momencie uruchomienia pliku wsadowego.
A oto przykład pętli o niemożliwej do ustalenia z góry liczbie powtórzeń:
:Start CHOICE /C:TN "Powtórzyć ?" IF ERRORLEVEL 2 GOTO Koniec GOTO Start :Koniec
Przerwanie pętli następuje w momencie naciśnięcia klawisza 'N' - nie można z góry przewidzieć ile razy użytkownik wybierze odpowiedĽ 'T'.
Instrukcja iteracyjna FOR pliku wsadowego jest pętlą o znanej liczbie powtórzeń i następującej składni:
FOR %%X IN (lista) DO komenda
Argument lista jest obowiązkowy i zawiera pooddzielane znakami odstępu nazwy plików - w nazwach tych mogą występować znaki wieloznaczne '?' i '*'. Po znakach '%%' pojemy tzw. zmienną - odpowiednik niewiadomej w matematyce. Zmienna ta będzie kolejno przybierać wszystkie możliwe wartości spośród wartości podanych na liście (lista). Dla każdej możliwej wartości zmiennej X zostanie wykonane polecenie komenda.
Rozważmy przykład:
[1] FOR %%A IN (1 2 3) DO DIR [2] FOR %%K IN (zadanie zadanie.bat zadanie.bak) DO DIR
Każda z powyższych instrukcji przyniesie ten sam efekt - trzy razy zostanie wykonane polecenie
DIR. W przykładzie [1] zmienna A przybierze (otrzyma) wartość "1" a nastepnie
nastąpi wykonanie polecenia DIR. Po wykonaniu komendy zmienna A otrzyma wartość
"2" i ponownie nastąpi wykonanie komendy. po jej zakończeniu zmienna A otrzyma wartość
"3" i zostanie wykonana komenda. Na tym zakończy się wykonywanie polecenia FOR.
W przykładzie [2] będzie dokłądnie tak samo z tą tylko różnicą że zmienna będzie przyjmować
wartości "zadanie", "zadanie.bat" oraz "zadanie.bak".
Odpowiedź na pytanie po co zmienna przyjmuje wartości z listy staje się oczywista jeśli powiemy, że wyrażenie %%X może występować w treści podanej komendy i reprezentuje aktualną wartość zmiennej X, podobnie jak %1 reprezentuje pierwszy argument pliku wsadowego. Tak więc, wykonanie polecenia:
FOR %%A IN (1 2 3 4 5 6 7 8 9 0) DO ECHO Wartość zmiennej = %%A
spowoduje wypisanie dziesięciu linii zawierających tekst "Wartość zmiennej = " oraz
odpowiednią cyfrę z listy.
Polecenie
FOR %%A IN (*.txt *.bak) DO COPY %%A C:\TEMP
skopiuje wszystkie pliki z katalogu bieżącego z rozrzerzeniami txt lub bak do podanego katalogu C:\TEMP.