Laboratorium CMD/BAT – Rozwiązania zadań praktycznych
Poniżej znajdują się kompletne rozwiązania 10 zadań laboratoryjnych z zakresu programowania w powłoce CMD systemu Windows.
Każde rozwiązanie zawiera działający kod skryptu wsadowego (.cmd) wraz z opisem działania oraz wskazówkami uruchomienia.
Wszystkie skrypty zostały zweryfikowane pod kątem poprawności składniowej.
Zadanie 1: System rejestracji użytkowników
Rozwiązanie:
Skrypt realizuje interaktywny system rejestracji użytkowników z walidacją danych i zapisem do pliku CSV.
Opis działania:
- Polecenie
@echo off wyłącza wyświetlanie poleceń w trakcie wykonania skryptu, pokazując tylko wyniki
- Konstrukcja
setlocal EnableDelayedExpansion aktywuje rozszerzone wykonywanie zmiennych przez !zmienna!
- Etykieta
:start oznacza punkt początkowy pętli rejestracji użytkownika
- Polecenie
set "LOGIN=" inicjuje puste zmienne dla danych użytkownika
- Polecenie
set /p LOGIN="Podaj login: " pobiera dane od użytkownika, gdzie flaga /p oznacza prompt interaktywny
- Konstrukcja warunkowa
if not defined LOGIN sprawdza czy zmienna LOGIN jest zdefiniowana
- Skok
goto start powoduje powrót do początku pętli w przypadku błędu walidacji
- Sprawdzenie unikalności loginu realizowane jest przez pętlę
for /f "tokens=1 delims=," %%A in ('type "%PLIK_CSV%"')
- Polecenie
type "%PLIK_CSV%" wyświetla zawartość pliku CSV jako dane wejściowe do pętli
- Konstrukcja
if not exist "%PLIK_CSV%" sprawdza czy plik CSV już istnieje w systemie plików
- Tworzenie nagłówka pliku CSV realizowane jest przez
echo Login,Imie,Nazwisko,Dzial > "%PLIK_CSV%"
- Operator przekierowania
>> dopisuje dane na końcu istniejącego pliku bez nadpisywania
- Zmienna
DUPLIKAT=0 służy jako flaga do wykrywania zduplikowanych loginów
- Warunek
if "%%A"=="%LOGIN%" porównuje login z linii pliku z wprowadzonym loginem
- Polecenie
echo %LOGIN%,%IMIE%,%NAZWISKO%,%DZIAL% >> "%PLIK_CSV%" zapisuje dane rozdzielone przecinkami
- Etykieta
:ask_again służy do pytania o dodanie kolejnego użytkownika
- Warunek
if /i "%ODPOWIEDZ%"=="T" sprawdza odpowiedź (flaga /i ignoruje wielkość liter)
- Polecenie
endlocal kończy lokalny zakres zmiennych i przywraca środowisko
- Kod wyjścia
exit /b 0 zwraca 0 przy poprawnym zakończeniu, 1 przy błędzie
Zadanie 2: Analizator struktury katalogów
Rozwiązanie:
Skrypt rekurencyjnie analizuje katalog i generuje raport z podsumowaniem rozmiarów według rozszerzeń.
Opis działania:
- Argument skryptu dostępny jest jako
%~f1 zwracający pełną ścieżkę bezwzględną
- Konstrukcja
if "%~1"=="" sprawdza czy argument został przekazany
- Polecenie
powershell -Command "Get-Date -Format 'yyyyMMdd_HHmmss'" pobiera znacznik czasu z PowerShell
- Pętla
for /R "%START_DIR%" %%F in (*) do rekurencyjnie przechodzi wszystkie pliki w katalogu
- Zmienna
%%~zF zwraca rozmiar pliku w bajtach
- Zmienna
%%~xF zwraca rozszerzenie pliku w formacie .rozszerzenie
- Konstrukcja
set "EXT=!EXT:~1!" usuwa pierwszy znak (kropkę) z rozszerzenia
- Walidacja rozszerzenia przez warunek
if /i "!EXT!"=="pdf" (flaga /i ignoruje wielkość liter)
- Zmienne inkrementowane są przez
set /a TOTAL_FILES+=1 gdzie flaga /a oznacza operację arytmetyczną
- Funkcja :format_size wykonywana jest przez polecenie
call :format_size S1 %TOTAL_SIZE%
- Konstrukcja
setlocal tworzy lokalny zakres zmiennych wewnątrz funkcji
- Przekazywanie wyniku przez
endlocal & set "%~1=%RESULT%" łączące endlocal z set
- Formatowanie rozmiaru przez próg gigabajtów:
if %SIZE% GEQ 1073741824
- Obliczanie części ułamkowej przez operator modulo:
set /a REST%%=1073741824
- Zapis raportu realizowany jest przez wielokrotne przekierowanie
>> "%RAPORT%"
- Kod wyjścia
exit /b 0 zwracany jest przy poprawnym zakończeniu analizy
Zadanie 3: Kalkulator z obsługą błędów
Rozwiązanie:
Skrypt kalkulatora przyjmujący dwa argumenty liczbowe oraz operator z pełną walidacją.
Opis działania:
- Argumenty pozycyjne dostępne są jako zmienne
%1, %2, %3
- Konstrukcja
%~n0 zwraca nazwę skryptu bez rozszerzenia do wyświetlenia pomocy
- Walidacja liczby argumentów przez warunek
if "%~2"=="" sprawdzający czy drugi argument istnieje
- Polecenie
echo %LICZBA1% | findstr /r "^[0-9-]*$" >nul waliduje czy argument jest liczbą
- Flaga
/r w findstr oznacza tryb wyrażenia regularnego
- Przekierowanie
>nul ukrywa wynik polecenia findstr
- Sprawdzenie errorlevel przez
if errorlevel 1 gdzie wyższy numer oznacza większy błąd
- Walidacja przez polecenie arytmetyczne
set /a TEST=LICZBA1 2>nul
- Przekierowanie
2>nul ukrywa błędy z polecenia set /a
- Konstrukcja warunkowa operatorów przez
if "%OPERATOR%"=="+"
- Obliczanie wyniku przez
set /a WYNIK=LICZBA1 + LICZBA2
- Sprawdzenie dzielenia przez zero:
if %LICZBA2%==0
- Obsługa modulo przez
set /a WYNIK=LICZBA1 %% LICZBA2 gdzie %% jest operatorem modulo
- Wyświetlenie błędu do strumienia błędów przez
echo Błąd: >&2
- Kod wyjścia
exit /b 1 zwracany jest przy błędzie walidacji
- Wyświetlenie wyniku przez polecenie
echo %LICZBA1% %OPERATOR% %LICZBA2% = %WYNIK%
Plik rozwiązania:
Pobierz 02_cmd_z03.cmd
Uruchomienie:
02_cmd_z03.cmd 10 5 +
02_cmd_z03.cmd 100 3 /
02_cmd_z03.cmd 15 4 %%
Zadanie 4: Backup rotator z czyszczeniem starych kopii
Rozwiązanie:
Skrypt tworzy kopię zapasową z automatyczną retencją i logowaniem.
Opis działania:
- Domyślna ścieżka źródłowa ustawiana jest przez
set "SOURCE=%USERPROFILE%\Documents"
- Zmienna środowiskowa
%USERPROFILE% zwraca ścieżkę do katalogu użytkownika
- Konstrukcja
%~f1 konwertuje argument na pełną ścieżkę bezwzględną
- Tworzenie katalogu przez polecenie
mkdir "%DEST%" 2>nul
- Przekierowanie
2>nul ukrywa komunikaty błędów mkdir
- Polecenie PowerShell
Get-Date -Format 'yyyy-MM-dd_HH-mm-ss' generuje znacznik czasu
- Tworzenie podkatalogu backup przez polecenie
mkdir "%BACKUP_DIR%" 2>nul
- Kopiowanie plików przez
xcopy /e /i /h /y "%SOURCE%" "%BACKUP_DIR%\"
- Parametry xcopy: /e (podkatalogi), /i (jeśli nie istnieje), /h (ukryte), /y (potwierdzenie)
- Sprawdzenie kodu wyjścia xcopy przez
if errorlevel 1
- Zmienna
%errorlevel% przechowuje kod wyjścia ostatniego polecenia
- Pętla zliczająca kopie:
for /d %%D in ("%DEST%\*") do
- Sortowanie katalogów według daty przez
dir /ad /b /o-d "%DEST%"
- Flagi dir: /ad (tylko katalogi), /b (bez nagłówka), /o-d (sortowanie oldest)
- Funkcja logowania wywoływana jest przez
call :log "tekst"
- Zapis do pliku logu przez
echo [%DATE% %TIME%] %~1 >> "%LOG_FILE%"
- Usuwanie starych kopii przez polecenie
rmdir /s /q "!OLD_DIR!"
- Parametry rmdir: /s (z podkatalogami), /q (tryb cichy)
- Kończenie przez goto :eof kończące wykonanie skryptu
Plik rozwiązania:
Pobierz 02_cmd_z04.cmd
Uruchomienie:
02_cmd_z04.cmd "C:\Projekty" "D:\Backup"
02_cmd_z04.cmd
Zadanie 5: Parser plików konfiguracyjnych INI
Rozwiązanie:
Skrypt parsuje pliki INI i zwraca wartości kluczy lub listę kluczy w sekcji.
Opis działania:
- Argumenty dostępne są jako
%~f1 (pełna ścieżka), %~2 (sekcja), %~3 (klucz)
- Sprawdzenie argumentów przez warunek
if "%~1"=="" wyświetlający pomoc
- Konstrukcja
usebackq pozwala na cytowanie nazw plików ze spacjami
- Polecenie
for /f "usebackq tokens=1,2 delims==" %%A in ("%INI_FILE%") do
- Flagi for /f: usebackq (cytowanie), tokens (wyodrębniane kolumny), delims (separator)
- Zmienna
%%A przechowuje pierwszy token (klucz), %%B drugi (wartość)
- Zastąpienie separatora przez
for %%T in (= :) do set "VALUE=!VALUE:%%T=!"
- Znajdowanie sekcji przez
echo !LINE! | findstr /b /r /c:"^\["
- Flagi findstr: /b (beginning), /r (regex), /c: (literal)
- Warunek
if not errorlevel 1 sprawdza czy znaleziono wzorzec
- Sprawdzenie czy jesteśmy w sekcji przez
if "!CURRENT_SECTION!"=="[%SEKCJA%]"
- Pominięcie komentarzy przez
findstr /r "^[^#;].*="
- Pominięcie pustych wartości przez
if "!VALUE!" neq ""
- Bez argumentu klucza wyświetlane są wszystkie klucze w sekcji
- Z argumentem klucza porównanie
if /i "!LINE!"=="%KLUCZ%"
- Goto przyspieszające wyjście:
goto done wychodzi z pętli
- Kody wyjścia zwracane przez
exit /b 1 przy błędzie
Plik rozwiązania:
Pobierz 02_cmd_z05.cmd
Uruchomienie:
02_cmd_z05.cmd config.ini Database host
02_cmd_z05.cmd config.ini Database
Zadanie 6: Generator haseł jednorazowych
Rozwiązanie:
Skrypt generuje bezpieczne hasła z opcjonalnymi znakami specjalnymi.
Opis działania:
- Definicja zbiorów znaków przez zmienne:
set "MAZE=ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- Zmienna
set "MALE=abcdefghijklmnopqrstuvwxyz" zawiera małe litery
- Zmienna
set "CYFRY=0123456789" zawiera cyfry
- Zmienna
set "SPECJALNE=@#$%%^&" zawiera znaki specjalne
- Polecenie
cls czyści ekran konsoli przed wyświetleniem menu
- Menu wyświetlane jest przez wielokrotne polecenie
echo
- Input przez
set /p WYBOR="Twój wybór (8/12/16/20/24): "
- Walidacja wyboru przez serię warunków
if "%WYBOR%"=="8" goto continue
- Etykieta
:continue oznacza punkt przejścia po poprawnym wyborze
- Pobranie opcji znaków specjalnych przez
set /p SPECJALNE_YN="Użyć znaków specjalnych? (T/N): "
- Losowanie indeksu przez
set /a IDX1=!RANDOM! %% 26
- Zmienna
%random% zwraca liczbę z zakresu 0-32767
- Operator modulo %% zwraca resztę z dzielenia przez długość zbioru
- Ekstrakcja znaku przez
set "H1=!MAZE:~%IDX1%,1!"
- Składnia ~start,length wycina podciąg ze zmiennej
- Łączenie ciągów przez
set "HASLO=!H1!!H2!!H3!"
- Pętla for do losowania dodatkowych znaków:
for /l %%N in (1,1,!ROZNICA!) do
- Flaga /l oznacza pętlę licznikową
- Wybór typu znaku losowy:
set /a TYP=!RANDOM! %% 4
- Walidacja opcji specjalnych:
if /i "%SPECJALNE_YN%"=="T"
- Wyświetlenie hasła tylko raz przez
echo !HASLO!
- Opcja nowego hasła realizowana przez warunek i skok do etykiety :generate
- Kod wyjścia 0 przy poprawnym zakończeniu
Zadanie 7: Monitor zajętości dysku z alertami
Rozwiązanie:
Skrypt monitoruje dyski i generuje raport z wizualizacją ASCII.
Opis działania:
- Argument domyślny przez konstrukcję
if "%~1"=="" set "DISKS=C"
- Próg alertu ustawiany przez
if "%~2"=="" set "THRESHOLD=90"
- Iteracja po dyskach przez pętlę
for %%D in (%DISKS%) do
- Rozdzielanie listy dysków przez CMD automatycznie traktuje przecinki jako separatory
- PowerShell do pobierania danych dysku:
Get-PSDrive -Name !DYSK!
- Rozszerzenie właściwości przez
Select-Object -ExpandProperty Used
- Przechwytywanie wyjścia przez pętlę
for /f "tokens=2" %%A in ('powershell ...') do
- Obliczanie całkowitego rozmiaru:
set /a CALKOWITE=UZYTE + WOLNE
- Obliczanie procenta zajętości:
set /a PROCENT=UZYTE * 100 / CALKOWITE
- Funkcja :check_single_disk wywoływana przez
call :check_single_disk
- Wizualizacja ASCII tworzona jest przez pętlę generującą znaki #
- Długość paska obliczana:
set /a BARS_COUNT=PROCENT / 2
- Pasek pustych znaków:
for /l %%B in (!BARS_COUNT!,1,50)
- Warunek alertu przez
if !PROCENT! GEQ %THRESHOLD%
- Licznik alertów inkrementowany przez
set /a ALERT_COUNT+=1
- Funkcja :format_bytes konwertuje bajty na jednostki
- Formatowanie TB:
if %SIZE% GEQ 1099511627776
- Formatowanie GB:
if %SIZE% GEQ 1073741824
- Formatowanie MB:
if %SIZE% GEQ 1048576
- Formatowanie KB:
if %SIZE% GEQ 1024
- Zapis raportu przez wielokrotne przekierowanie >>> do pliku
- Wyświetlanie podsumowania:
echo Podsumowanie: !ALERT_COUNT! alertów
- Kod wyjścia zwraca wynik operacji monitorowania
Zadanie 8: Wsadowa konwersja kodowania plików
Rozwiązanie:
Skrypt konwertuje pliki tekstowe między kodowaniami z zachowaniem struktury.
Opis działania:
- Argumenty: źródło, cel, kodowanie_z, kodowanie_do
- Domyślne kodowania ustawiane przez
if "%FROM_ENC%"=="" set "FROM_ENC=ANSI"
- Sprawdzenie źródła:
if not exist "%SOURCE%"
- Tworzenie katalogu docelowego:
if not exist "%DEST%" mkdir "%DEST%"
- Funkcja :map_encoding mapuje nazwy kodowania na format PowerShell
- Mapowanie UTF8:
if /i "%ENC%"=="UTF8" set "RESULT=UTF8"
- Mapowanie UTF16:
if /i "%ENC%"=="UTF16" set "RESULT=Unicode"
- Iteracja po plikach:
for /R "%SOURCE%" %%F in (*.txt *.html *.htm *.css *.js *.xml *.json) do
- Zmienna
%%~fF zwraca pełną ścieżkę pliku
- Zmienna
%%~nxF zwraca nazwę z rozszerzeniem
- Obliczanie ścieżki względnej:
set "REL_PATH=!FILE_PATH:%SOURCE%=!"
- Usuwanie pierwszego znaku:
set "REL_PATH=!REL_PATH:~1!"
- Tworzenie podkatalogów:
if not exist "!DEST_DIR!" mkdir "!DEST_DIR!"
- PowerShell konwersja:
Get-Content -Path '!FILE_PATH!' -Encoding %FROM_PS%
- Zapis z kodowaniem:
Set-Content -Path '!OUT_FILE!' -Encoding %TO_PS%
- Sprawdzenie błędów:
if errorlevel 1
- Liczniki:
set /a COUNT_OK+=1, set /a COUNT_ERR+=1
- Komunikaty postępu wyświetlane przez
echo [OK] !FILE_NAME!
- Podsumowanie wyjściowe zawiera statystyki udanych i nieudanych konwersji
- Kod wyjścia 1 gdy są błędy:
if %COUNT_ERR% GTR 0 exit /b 1
Plik rozwiązania:
Pobierz 02_cmd_z08.cmd
Uruchomienie:
02_cmd_z08.cmd C:\txt D:\txt_utf8 ANSI UTF8
02_cmd_z08.cmd C:\docs D:\docs_converted
Zadanie 9: Automatyczna dokumentacja folderu
Rozwiązanie:
Skrypt generuje dokumentację w formacie Markdown z drzewem katalogów.
Opis działania:
- Argument pobierany jako
%~f1 z konwersją na pełną ścieżkę
- Pytanie o ścieżkę:
set /p ROOT_DIR="Podaj ścieżkę do dokumentowania: "
- Sprawdzenie istnienia:
if not exist "%ROOT_DIR%"
- Generowanie nazwy pliku wyjściowego:
set "OUTPUT=%DIR_NAME%_dokumentacja_%TS%.md"
- Polecenie PowerShell do pobrania timestamp:
Get-Date -Format 'yyyy-MM-dd_HH-mm-ss'
- Funkcja :get_parent_name wyodrębnia nazwę katalogu
- Funkcja :generate_doc generuje strukturę dokumentu Markdown
- Nagłówek Markdown:
echo # Dokumentacja: %PARENT_NAME% > "%OUTPUT%"
- Operator > tworzy nowy plik lub nadpisuje istniejący
- Spis treści generowany przez pętlę po katalogach:
for /d /r "%ROOT_DIR%" %%D in (*)
- Konwersja nazwy na anchor:
set "ANCHOR=!DIR_NAME: =-!"
- Zastępowanie znaków w zmiennej przez konstrukcję : = -
- Link do sekcji w Markdown:
echo !TOC_NUM!. [Dir: !DIR_NAME!](#!ANCHOR!) >> "%OUTPUT%"
- Funkcja :doc_section generuje opis każdego katalogu
- Sprawdzenie README w podkatalogu:
if exist "%%D\README.md"
- Odczytywanie zawartości README przez pętlę for /f
- Struktura plików generowana przez polecenie dir z parametrami
- Obliczanie rozmiaru pliku przez
%%~zF
- Formatowanie MB:
set /a SIZE_MB=FILE_SIZE / 1048576
- Formatowanie KB:
set /a SIZE_KB=FILE_SIZE / 1024
- Zliczanie plików przez pętlę:
for /r "%ROOT_DIR%" %%F in (*) do set /a TOTAL_FILES+=1
- Kod wyjścia przy poprawnym zakończeniu
Zadanie 10: Menedżer zadań systemowych
Rozwiązanie:
Interaktywny menedżer zadań Windows Task Scheduler z menu.
Opis działania:
- Menu główne wyświetlane przez polecenie
echo z opcjami
- Etykieta
:menu oznacza punkt powrotu do menu
- Polecenie
cls czyści ekran przed wyświetleniem menu
- Input wyboru:
set /p WYBOR="Twoj wybor (1-7): "
- Obsługa wyborów przez warunki
if "%WYBOR%"=="1" goto list_tasks
- [1] Lista zadań:
schtasks /query /fo LIST
- Parametry schtasks: /query (lista), /fo FORMAT, /v (szczegóły)
- Sprawdzenie errorlevel po schtasks przez
if errorlevel 1
- [2] Szczegóły zadania:
schtasks /query /tn "%TASK_NAME%" /fo LIST /v
- Parametr /tn określa nazwę zadania (Task Name)
- [3] Tworzenie zadania realizowane jest przez schtasks /create
- Parametry /create: /tn (nazwa), /tr (polecenie), /sc (harmonogram), /st (czas)
- Harmonogramy: DAILY, WEEKLY, ONCE, ONSTART
- [4] Usuwanie zadania:
schtasks /delete /tn "%TASK_NAME%" /f
- Parametr /f wymusza usunięcie bez potwierdzenia
- [5] Włączanie/wyłączanie:
schtasks /change /tn "%TASK_NAME%" /enable
- Parametr /disable wyłącza zadanie
- [6] Historia zadania pobierana jest przez query ze szczegółami
- Sprawdzenie uprawnień przez próbę wykonania schtasks
- Input nazwy zadania przez
set /p TASK_NAME="Nazwa zadania: "
- Input polecenia:
set /p TASK_CMD="Polecenie do wykonania: "
- Input harmonogramu:
set /p TASK_SCHEDULE="Harmonogram (DAILY, WEEKLY, ONCE): "
- Input czasu:
set /p TASK_TIME="Godzina uruchomienia (np. 09:00): "
- Potwierdzenie usunięcia:
set /p CONFIRM="Na pewno usunac? (T/N): "
- Walidacja potwierdzenia:
if /i not "%CONFIRM%"=="T"
- Etykieta :end wyświetla pożegnanie i kończy skrypt
- Polecenie
goto :eof kończy wykonanie skryptu
- Kod wyjścia zwracany jest przez endlocal
Plik rozwiązania:
Pobierz 02_cmd_z10.cmd
Uruchomienie:
02_cmd_z10.cmd
(Uruchom jako administrator dla pełnej funkcjonalności)
Podsumowanie
- Wszystkie 10 zadań zostały rozwiązane
- Każdy skrypt zweryfikowany pod kątem poprawności składniowej CMD/BAT
- Skrypty zawierają walidację błędów i odpowiednie kody wyjścia
- Pliki gotowe do uruchomienia w systemie Windows
- Wymagane: terminal cmd.exe z dostępem do systemu Windows
- Niektóre operacje (schtasks) wymagają uprawnień administracyjnych