Windows NT obsahují Příkazový řádek (anglicky Windows Console), který je nástupcem MS-DOS (používaným před a ve Windows 9x). Příkazový řádek (též konzola nebo hovorově konzole) používá stejné příkazy jako jeho předchůdce, navíc ale obsahuje celou řadu rozšíření, které ne vždy všichni ovládají. Nástupce Příkazového řádku je Microsoft PowerShell, který podporuje původní příkazy MS-DOS, ale místo rozšíření Příkazového řádku používá vlastní funkce a syntaxy.
Stejně jako v MS-DOS bylo možno psát skripty do BATCH souborů (*.bat), v Příkazovém řádku je možno spouštět skripty ze souborů s příponou *.cmd (zkratka commands). Skript můžete spustit zadáním jeho jména v příkazovém řádku (uvedení přípony není nutné) nebo dvoj-klikem na jeho soubor v Průzkumníku (nejiném programu, např. Total Commanderu). Skript nejde připnout k Panelu úkolů. Pokud připnete běžící skript, připne se pouze Příkazový řádek a ne konkrétní skript. Pokud zkusíte skript zkopírovat do Pinned\TaskBar, budou ho Windows ignorovat.
Rychlá navigace
Vkládání jmen souborů s mezerami
MS-DOS mezery ve jménech souborů nepodporoval, takže tento problém neexistovat. Ve Windows ale není problém pojmenovat soubor s mezerou. Aby šla tato jména uvádět do Příkazové řádky, můžete jméno, celou cestu, nebo její část uvést do dvojitých uvozovek (jiné uvozovky nefungují). Příklady platných jmen souborů a složek:
"C:\Program Files\Windows Photo Viewer""C:\Program Files"\"Windows Photo Viewer"C:\"Program Files"\"Windows Photo Viewer""C:\Program Files"\WindowsPowerShell
Pozor na to, že při používání uvozovek uvnitř skriptu nebo při volání skriptu může mít různé účinky! Uvedení uvozovek u parametru může uvozovky předat do skriptu nebo dokonce způsobit chybu syntaxe (viz dále).
Když máte spuštěný Příkazový řádek, můžete také přetáhnout soubor z Průzkumníka do konzole a ta automaticky vypíše jméno tohoto souboru. Pokud vyberete více souborů, vloží se jen jméno toho, který táhnete.
Automatické dokončování jmen souborů
Když píšete v Příkazovém řádku jméno souboru nebo složky, můžete stiskem klávesy TAB požádat systém o automatické dokončení jména. Konzole doplní jméno prvního souboru nebo složky, jehož jméno odpovídá již zadanému textu. Dalšími stisky TAB můžete doplnit jméno dalších souborů nebo složek odpovídajících původnímu textu.
Příklad: pokud zadáte do konzole c:\pro a stisknete TAB, automaticky se dokončí "C:\Program Files" (včetně uvozovek). Další stisk TAB pak změní cestu na "C:\Program Files (x86)" (pouze na 64-bit Windows) nebo na C:\ProgramData.
Skrytí kódu a výpisu skriptu
Když spustíte skript, bude konzole vypisovat jednotlivé příkazy a jejich výstup. Pokud chcete skript spustit jako program, tedy aby nebylo vidět, z jakých příkazů se skrývá, zadejte na začátek souboru:
echo off
Tím vypnete výpis spuštěných příkazů a zobrazí se pouze výstup jednotlivých příkazů.
Pokud chcete skript debuggovat, můžete první příkaz změnit na echo on, nebo echo on uvést kamkoliv do skriptu a další příkazy se opět budou vypisovat. Pokud uvedete jen „echo“ bez parametru, vypíše se „echo off“ nebo „echo on„, podle toho, jaký je aktuální stav (hodí se pro debuggování při použití goto nebo call).
Vlastní text pak můžete vypsat příkazem echo a uvedením libovolného jiného textu (tedy cokoliv kromě „off“ a „on„). Prázdný řádek vypíšete zadáním echo. (tedy uvedením tečky bez mezery za echo).
Pokud chcete skrýt výstup konkrétního příkazu, můžete za něj uvést > NUL:
process > NULL
Toto se často používá v kombinaci příkazů echo a pause, kdy chcete místo výchozího textu „Stiskněte libovolnou klávesu pro pokračování“ zobrazit jiný text:
... echo První část dokončena. echo Stiskněte libovolnou klávesu pro spuštění druhé části. pause > NUL ...
Pokud chcete výstup příkazu skrýt, ale nechcete o něj přijít, můžete ho nechat uložit do souboru:
process %1 > output.log process %2 >> output.log echo. >> output.log echo Dokončeno >> output.log
Uvedená sekvence vytvoří nový soubor output.log (nebo přepíše existující) a následně do něj přidá výstup prvního a druhého příkazu. Na konec soubor pak přidá prázdný řádek a text „Dokončeno“.
Poznámka: existuje i opačný operátor, pomocí něhož můžete obsah souboru předat příkazu jako vstup. V tomto případě ale musí daný příkaz být schopen vstup zpracovat:
process %1 -value=%2 < input.txt
Skrytí nebo uložení chybového výstupu
I když použijete > NUL nebo > file.txt (které přesměrovává tzv. STDOUT), může program stále do konzole vypisovat chyby (a některé programy to používají k tomu, aby vypsali tzv. hlavičku). Tento výstup (tzv. STDERR) přesměrujete použitím 2> za příkazem:
process > NUL 2> NUL process >> output.txt 2>> error.log //alternativa prvního příkazu (přesměruje výstup STDOUT do NUL a následně STDERR to STDOUT což povede k tomu, že STDERR skončí také v NUL): process 1> NUL 2>&1
Titulek okna
Když spustíte Batch (nebo Command) skript ve Windows, výstup ze zobrazí v okně, které má jméno „C:\Windows\System32\cmd.exe“, což není pěkné.
Titulek okna můžete nastavit příkazem title. Použít můžete třeba jméno skriptu, nebo v něm zobrazovat průběh:
title Spouštění skriptu %~n0... prepare %* :start title Zpracování souboru %1... process %1 shift if not [] == [%1] goto start title Dokončeno pause > NUL
Podpora češtiny
Pokud chcete, aby skript vypisoval české hlášky včetně diakritiky, musíte změnit kódovou stránku příkazové řádky (protože i v českých Windows je výchozí anglická kódová stránka, která nepodporuje české znaky).
Provedete to příkazem chcp 1250 na začátku souboru:
@echo off chcp 1250 title Skript %~n0 běží a zpracovává soubory...
Pozor na to, že takový skript musíte následně uložit s kódováním „ANSI 1250“ (nebo Windows 1250, CP-1250 či ISO 8859-2 dle možností editoru); některé moderní editory a IDE ukládají soubory v UTF-8, což není ve skriptech podporováno!
Parametry skriptu
Skriptu můžete předat parametry. Pokud spouštíte skript z příkazové řádky, stačí parametry zadat za jméno skriptu:
> script.cmd param1 param2 param3 > script param1 param2 params3
Normálně můžete předat skriptu až 9 parametrů. K nim se pak ve skriptu dostanete zadáním %1, %2, atd. až %9. Pokud chcete použít více parametrů, podívejte se dále na Cyklické zpracování parametrů.
Příklad:
echo Příprava %1 s hodnotou %2. prepare %1 -value=%1 echo Ukládání do %3... Process %1 -output=%3
Předání souborů skriptu
Skript můžete spustit s parametrem i z Průzkumníka (nebo Plochy; ale ne z jiných programů jako Total Commander) tím, že označíte soubory (v Průzkumníku nebo jiném programu, třeba Total Commander) a přetáhnete je na ikonu skriptu. Tímto způsobem ale můžete skriptu předat pouze seznam souborů a ne žádné další parametry.
Z příkazové řádky můžete soubory předat skriptu zadáním jmen za jméno skriptu:
> skript soubor1.txt "soubor 2.txt"
Tímto způsobem můžete ale předat jen omezené množství souborů, nicméně na početní omezení narazíte jen při přetažení velkého množství souborů (50 nebo více v závislosti na délce jejich jmen).
Při zadávání jmen do konzole s uvozovkami se jména souborů předají včetně uvozovek. Při přetažení z Průzkumníka se jména souborů předají bez uvozovek (ale se správně ošetřenými mezerami ve jménech). Na to je potřeba dávat pozor při dalším zpracování!
Získání parametru ve skriptu
Uvnitř skriptu můžete použít konkrétní skript zadáním %X, kde X je číslo 1 – 9. Tato základní syntaxe z MS-DOS je v Konzoly rozšířena o možnost získání jen části parametru, pokud jde o jméno souboru. Můžete tak například získat jen jméno, příponu nebo cestu k souboru a následně s nimi pracovat odděleně.
Díky tomu, že vložení parametru začíná znakem procent a končí jednou číslicí, není potřeba ho oddělovat od dalšího textu. Klidně tak můžete přidat příponu souboru jednoduše tím, že za číslo parametru zadáte tečku a příponu (viz příklad níže).
Ze jména souboru v parametru můžete získat následující části:
%~1vrátí první parametr jak je, jen odstraní uvozovky%~f1vrátí plné jméno (fullname) souboru včetně cesty%~n1vrátí jen jméno souboru (name) bez cesty a přípony%~x1vrátí příponu souboru (s tečkou; např. „.txt„)%~d1vrátí písmeno disku, na kterém je soubor (např.C:)%~p1vrátí cestu k souboru v unix formátu (např.\path\)%~dp1vrátí cestu k souboru včetně disku (např.C:\path\)%~nx1vrátí jméno souboru s příponou (např.file.txt)%~dpn1vrátí celé jméno souboru vč. cesty, ale bez přípony (užitečné pro převod souboru).- přidání „
s“ do filtru parametru převede všechna jména na DOS formát (8.3), např. %~sp1 vrátí cestu se složkami v 8.3 formátu, %~sx1 vrátí příponu zkrácenou na 3 písmena, apod. %~a1vrátí atributy souboru%~t1vrátí čas vytvoření souboru%~z1vrátí velikost souboru%~ $PATH:1zkusí najít soubor ve složkách uvedených v PATH a vrátí celé jméno vč- cesty pro první nalezený soubor.
rem Zpracování souboru s cestou: process %1 rem Zpracování souboru, nejprve přepnutí do jeho složky: cd %~dp1 process %nx1 rem Zpracování souboru a uložení s novou příponou process -i %~1 -i %~dpn1.xml
Nultý parametr = jméno skriptu nebo předchozí hodnota
Ve skriptu můžete použít i nultý parametr, ve kterém je uloženo jméno právě spuštěného skriptu.
Pozor ale na to, že příkaz SHIFT pracuje i s parametrem %0, takže po jeho zavolání bude v %0 uložen „již zpracovaný parametr“ a už ne jméno skriptu.
Pokud chcete jméno skriptu k něčemu používat po celou dobu jeho běhu, je potřeba si ho uložit do proměnné:
set self=%0 :start process %1 shift if not [] == [%1] goto start echo Skript %self% dokončil zpracování všech parametrů
Naopak při cyklyckém zpracování můžete můžete %0 použít pro přístup k předchozímu parametru, pokud ho potřebujete. V některých situacích je to lepší, než pracovat s %1 a %2 a kontrolovat, zda ještě existuje další parametr připravený ke zpracování (zvláště, pokud je potřebujete nejprve oba zpracovat).
set self=%0 :start process %1 rem Zjistí, zda aktuálně zpracovaný soubor je stejně velký jako předchozí if not [%self%] == [%0] if %~z0 == %~z1 echo %0 je stejně velký jako %1 shift if not [] == [%1] goto start
Podmíněné zpracování podle jména/obsahu souboru
Pokud do skriptu předáte jméno souboru, můžete zpracování podmínit tím, že si uložíte příponu (set file_type=%~x1) a pak ji porovnáte proti podporovaným typům (if [txt] == [%file_type%] goto process_txt).
To jistě stačí pro základní podmínky, ale můžete narazit na potřebu složitějšího rozpoznání souboru podle jména nebo obsahu. K tomu slouží funkce findstr.
Například pokud chcete zpracovat textový soubor jinak, pokud obsahuje text „tajné“:
findstr "tajné" %1 > NUL if [0] == [%ERRORLEVEL%] goto process_secret if [1] == [%ERRORLEVEL%] goto process_public
Funkce findstr vrátí hodnotu (ERRORLEVEL) rovnu 0, pokud byl řetězec nalezen v obsahu souboru (%1), nebo 1, pokud nalezen nebyl. Funkce také vypíše řádek, ve kterém byl text nalezen – pokud hledáte text v BATCH skriptu, je obvykle lepší přesměrovat výstup pro jeho skrytí (> NUL).
Pro hledání více různých slov je můžete oddělit mezerou; například findstr "tajné secret soukromé private" %1 vyhledá různé varianty označení tajného souboru. V důsledku toho ale není funkce schopna hledat řetězce obsahující mezery! Dokáže ale hledat s použitím jednoduchých regulárních výrazů; například findstr "tajn[éýá]" %1 najde všechny tvary slova tajné (tedy i „tajný“ a „tajná“). Stejně tak findstr /I "^tajn[éýá]" %1 najde pouze řádek „Tajná zpráva“ (tedy na začátku řádky bez rozlišení velikosti), ale bude ignorovat stejná slova uprostřed textu (např. „Tento text není tajný“).
Pokud chcete stejné podmínky použít na jméno souboru, můžete využít toho, že findstr umí pracovat s výstupem předchozího příkazu. Stačí tedy vypsat jméno souboru a přesměrovat ho do funkce findstr:
echo %1 | findstr "tajn[éýá]" > NUL if [0] == [%ERRORLEVEL%] goto process_secret if [1] == [%ERRORLEVEL%] goto process_public
Pozor na to, že příkaz echo přidá do výstupu i mezeru mezi „%1“ a „|“. Pokud byste chtěli tímto způsobem ověřit konec jména suuboru (příponu apod.), je potřeba tuto mezeru vypustit:
echo %1| findstr ".sql.zip$" > NUL if [0] == [%ERRORLEVEL%] goto process_compressed_sql
Hodnoty ze souboru místo parametrů
Pokud máte příliš mnoho parametrů, které byste potřebovali předat skriptu (stovky, tisíce, a více) nebo nemají podobu jednoduchých textů (obvykle URL), můžete je zapsat do textového souboru (nebo použít jiný skript, který takový soubor vygeneruje) a následně je ze souboru načíst (v příkladech budu používat %1, aby šlo skript spustit tím, že na něj textový soubor přetáhnete) a zpracovat.
Windows Console dokáže načítat soubor po řádkách a volitelně po slovech (oddělený mezerou, stejně jako parametry v příkazové řádce).
Čtení souboru po řádcích
Pokud chcete načíst celý řádek a zpracovat ho jako jeden parametr, použijte tokens=*:
for /F "usebackq tokens=*" %%A in (%1) do call :process %%A goto :EOF :process process %1 exit /b
Poznámky: jak funguje call, goto a exit je vysvětleno pod Volání funkcí. Klíčové slovo usebackq povoluje mezeru ve jméně souboru %1 (mimo jiné, viz dále). Ve FOR uvnitř batch je potřeba použít dvojitý znak %% – pokud příkaz voláte přímo z příkazové řádky, použijte jen jedno %. Nejdůležitější je parametr /F, který říká, že in () se bude číst jako textový soubor (ale může jít i třeba o příkaz, který text vrací do konzole).
Pozor na to, že pokud řádek obsahuje mezery, je potřeba použít následující alternativu (uvozovky u %%A a %~1), aby se celý řádek zpracoval jako jeden parametr (proč viz dále):
for /F "usebackq tokens=*" %%A in (%1) do call :process "%%A" goto :EOF :process process %~1 exit /b
Čtení souboru po slovech
Pokud každý řádek souboru obsahuje (předem známý) počet „slov“ oddělených mezerou, můžete jednotlivá slova uložit do samostatných proměnných a následně zpracovat podle potřeby.
Tento skript načte první 3 slova z každé řádky:
for /F "usebackq tokens=1,2,3" %%A in (%1) do call :process %%A %%B %%C goto :EOF :process prepare %1 process %2 %3 exit /b
Nebo můžete přímo určit která slova chcete použít (a ostatní přeskočit). V dalším příkladu použijeme jen třetí a páté slovo z každé řádky:
for /F "usebackq tokens=3,5" %%A in (%1) do call :process %%A %%B goto :EOF :process process %1 %2 exit /b
Asi už jste si všimnuli, že pokud příkaz FOR vrací více hodnot, vždy zadáváje jen první a příkaz pak vytvoří další parametry v abecedním pořadí. Pokud tedy uvedete %%A, parametry budou %%A, %%B, %%C, atd. Pokud použijete programátorům známější %%i, další parametry budou %%j, %%k, %%l, atd.
Pokud chcete jen přeskočit některá (počáteční slova) a pak použít všechny ostatní, můžete použít hvězdičku za číslem (je jedno, jestli ji oddělíte čárkou nebo ne).
for /F "usebackq tokens=2*" %%A in (%1) do call :process %%A %%B goto :EOF :process process %1 shift if not [] == [%1] goto :process exit /b
Zde je potřeba dát si pozor na jednu věc: i když jsme uvedli 2* bez čárky, příkaz vrátí proměnné %%A a %%B. Navíc %%B bude obsahovat všechna slova (sloupce) včetně mezer, takže volání call :process %%A %%B nepředá funkci jen dva parametry, ale tolik parametrů, kolik je v řádku slov (v příkladu kromě prvního).
Pozor na to, že mezery na začátku řádky se vždy oříznou, takže jako první slovo je považována první neprázdná sekvence znaků.
Pokud potřebujete ze souboru načíst jen dvě slova, kde druhé může obsahovat mezery, je potřeba %%B uvést do uvozovek (a podle potřeby použít %~2 pro jejich odstranění).
Například skript, který přejmenuje soubory z formátu 8.3 do Windows (s podporou mezer):
for /F "usebackq tokens=1,*" %%A in (%1) do call :rename %%A "%%B" goto :EOF :rename ren %1 %2 exit /b
Ještě příklad takového souboru:
KomuZv~1.txt Komu zvoní ve věži.txt daně20~2.xls Daně 2020.xls devata.fla Devátá.flac
Čtení CSV a jiných souborů
Pokud máte soubor ve speciálním formátu jako je CSV (comma-separated values), můžete příkazu určit, jakými znaky jsou oddělany slova (resp. sloupce) a řádky.
Tento příklad zpracuje 2., 4. a 5. sloupec z CSV souboru (např. export databáze nebo Excel tabulky):
for /F "usebackq tokens=2,4,5 delims=,;" %%A in (%1) do call :process %%A %%B %%C goto :EOF :process process %1 %2 %3 exit /b
Poznámka: podle verze CSV nebo Excelu je možné použít čárku nebo středník, proto používáme delims=,;, abychom zahrnuly obě varianty. Pozor na to, že i když použijete parametr delims, mezera je vždy považována za oddělovač. Například tento CSV soubor bude načten do 4 slov:
001;Daně 2020.xls;164kB
Přečtení celého souboru
Pokud máte v souboru jen jednu hodnotu nebo prostě chcete načíst celý soubor do proměnné, stačí k tomu příkaz set s přesměrováním vstupu. To se často hodí k tomu, pokud míte jeden příkaz (program), který něco napíše do konzole a vy to potřebujete přečíst a uložit do proměnné. Stačí výstup uložit do souboru a pak ho ze souboru přečíst:
calculate.exe > result.txt
set /p result=<"result.txt"
Samozřejmě pokud je vstupní soubor předán jako parametr skriptu, můžete jméno přečíst z parametru:
set /p input=<"%~1"
Jen pozor na to, že zápis je citlivý na uvedené znaky – šipka (znak menší) musí následovat bez mezery za rovnítkem a jméno musí souboru musí být bez mezer (proto je lepší použít uvozovky a případně %~1, které odstraní uvozovky z parametru). Také nezapomeňte na /p, které říká příkazu, že hodnota se bude číst ze vstupu (typicky z klávesnice, ale zde je to ze souboru).
Uložení hodnoty do proměnné
Ve skriptech (ale i mimo ně) můžete používat proměnné. Ty se vytvářejí příkazem set, za který zadáte jméno proměnné, rovnítko a hodnotu. Vytvořenou proměnnou pak můžete v příkazu použít tak, že uvedete jméno proměnné mezi uvozovky. Při vytvoření proměnné můžete použít předdefinovanou hodnotu (tzv. hard-coded) nebo hodnotu z parametru:
set process=cbr set quality=%1 convert %process% -q %quality% %2
Pokud hodnotu nevytvoříte a zkusíte ji použít, nedojde k nahrazení a do příkazu se pošle přímo daný řetězec vč. znaků procent:
> echo Proměnná %tohle_neexistuje%. Proměnná %tohle_neexistuje%.
Dejte pozor na to, že hodnota je do proměnné vložena přesně tak, jak je vložena do skriptu až po znak nové řádky. Nejčastější chyby tak jsou ty, že za hodnotu vložíte mezeru, která není vidět, ale uloží se do proměnné, nebo že hodnotu uvedete do uvozovek (nebo jsou uvozovky uvedeny v parametru skriptu) a následně vložíte proměnnou také do uvozovek:
rem špatně (neviditelné mezery za hodnotou): set file=%1⏎rem správně (odřádkování hned za hodnotou): set file=%1⏎rem špatně (parametr může obsahovat uvozovky, takže budou zdvojené): set file=%1⏎process "%file%" rem špatně (ručně dodané uvozovky, budou zdvojené): set file="%1"⏎process "%file%" rem správně (jméno souboru bez uvozovek): set file=%~1⏎process "%file%" rem správně (očekáváme uvozovky v proměnné): set file="%~1"⏎process %file%
Další častá chyba bývá, že jméno proměnné uvedete do znaků procent. V tomto případě se místo vytvoření proměnné pod daným jménem vytvoří proměnné pod hodnotou dříve uloženou v proměnné nebo se vytvoří proměnná včetně procent, pokud dosud neexistuje:
set a=1 set %a%=2 rem vytvoří proměnnou "a" s hodnotou "1" a proměnnou "1" s hodnotou "2" set %b%=3 rem vytvoří proměnnou %b% s hodnotou 3
Interaktivní skript
Pokud chcete udělat skript interaktivní, můžete se na hodnotu parametru zeptat uživatele. Stačí příkazu set přidat parametr /P (prompt) a za rovnítko místo hodnoty zadat text dotazu:
set process=cbr
set /P quality=V jaké kvalitě chcete provést převod souboru %2? [např. 128, 196, 320]: ⏎
Poznámka: zde je naopak vhodné za text uvést mezeru, aby zobrazený dotaz nesplýval s hodnotou, kterou zadává uživatel.
Pokud chcete dotazu vytvořit výchozí hodnotu, stačí jí do proměnné uložit před dotazem. Uživateli pak stačí stisknout Enter a bude použita výchozí hodnota:
set process=cbr set quality=320 set /P quality=Zvolte kvalitu převodu [výchozí: 320]: convert %process% -q %quality% %1
Aritmetické výpočty aneb spočtení parametrů
Příkazem SET můžete provádět matematické výpočty, pokud použijete parametr /A (od výrazu Aritmetické operace).
set /A sum=%1 + %2 set %A diff=%1 - %2 echo Součet parametrů je %sum% echo Rozdíl parametrů je %diff%
Hodnotu můžete také inkrementovat tím, že dokola přičítáte jedničku:
set dokonceno=0 :start process %1 set /A dokonceno=%dokonceno% + 1 shift if not [] == [%1] goto :start echo Zpracováno %dokonceno% parametrů.
Pozor na to, že skripty pracují pouze s celými čísly. Není tedy možné například vynásobit proměnnou číslem 1,5 (jeden a půl krát), ale je potřeba vynásobit ho 3 a pak ho vydělit 2 (tři poloviny je jeden a půl). Stejně tak je potřeba brát v úvahu pořadí, protože zaokrouhlení (resp. oříznutí desetinných míst) se provádí po každém výpočtu. Například 3 * 3 / 2 je 4, zatímco 3 / 2 * 3 je 3, i když matematicky by výsledek měl být vždy 4,5 (resp. 4 po oříznutí desetinné části).
Práce s jmény souborů se speciálními znaky
Kromě mezery dělá Windows konsole problémy znak „&“, který slouží ke spojování příkazů:
rem V jediném řádku spustí process and vypíše dvě hlášky (před a po): echo Start & call process.cmd & echo End
Pokud do skriptu chcete předat jméno souboru nebo URL obsahující znak &, je potřeba ho escapovat znakem stříšky, tedy ^& nebo uvést do uvozovek:
process.cmd c:\Documents^&Settings\file.txt download.cmd http://server.com/download?name=file^&ext=txt process.cmd "c:\Documents&Settings\file.txt" download.cmd "http://server.com/download?name=file&ext=txt"
Pokud takový soubor přetáhnete na Batch skript, Windows přidají uvozovky automaticky:
echo off rem Drag&Drop souboru s mezeramy nebo & ve jméně je automaticky ošetřeno: process.exe %1
Pokud potřebujete ověřit, že byl parametr předán skriptu, můžete použít speciální kontrukci příkazu if s hranatými uvozovkami:
rem Selže pokud %1 obsahuje jméno souboru s uvozovkami: if "" == "%1" goto end rem Selže pokud skript zavoláte z konzole bez uvozovek: if "" == %1 goto end rem Funguje vždy správně; hranatá závorka se neduplikuje s uvozovkami: if [] == [%1] goto end
Problém nastává v okamžiku, kdy chcete ověřit, že soubor existuje nebo z něj vyparsovat části jméno (příponu, složku, apod.). V tom případě je potřeba vždy zachovat uvozovky kolem hodnoty parametru nebo hodnoty proměnné:
rem Odstraní uvozovky, přidá příponu a opět uvozovky přidá: set temp_filename="%~1.tmp" process -in %1 -out %temp_filename% rem Získání jména souboru a cesty (viz dále) včetně uvozovek: set filename="%~nx1" set filepath="%~p1" rem Přepnutí pracovní složky na disk a složku souboru: %~d1 cd %filepath% rem Zpracování souboru v jeho složce: c:\process.exe %filename% rem Proměnné můžete skládat dohromady a Konzola správně pochopí, co chcete: process -input %filename% -output %tmp%\%filename%.tmp
Jak je vidět, pokud části jména používáte pro vytvoření cesty a jména souboru, můžete používat hodnoty v uvozovkách a není problém s tím, že uvozovky jsou uloženy přímo v hodnotě proměnné. Jen je potřeba dát pozor, pokud chcete do jména přidat jméno se speciálními znaky, abyste správně použili uvozovky:
rem Tohle je špatně, protože vytvoří nevhodně zdvojené uvozovky:
process -input %filename%
-output "%filepath%temp folder & files\%filename%.tmp"
rem Tohle je správně (uvede v uvozovkách jen jméno složky):
process -input %filename%
-output %filepath%"temp folders & files\"%filename%.tmp
Pokud byste potřebovali získat jméno souboru bez uvozovek a uvést ho do příkazu v uvozovkách, můžete použít speciální konstrukci pro vložení proměnné s nahrazením znaku. To se provádí tak, že za jméno proměnné uvedete uvozovku, znak, který chcete odstranit a za rovnítko znak, který chcete vložit – jelikož ale chcete uvozovky odstranit a nic nevkládat, skončíme rovnítkem:
rem Získání jméno souboru set filename="%~n1" echo Processing %filename%… rem Pomocí FFMPEG vloží do popisu první stopy jméno souboru bez uvozovek: ffmpeg -i %1 -c copy -metadata:s:v:0 title="Ze souboru: %filename:"=%" %filename%.new.mkv
Poznámka: zápis uvozovek a procent v příkazu může některé „chytřejší“ editory zmást, ale je skutečně správně, že parametr title obsahuje 3 znaky uvozovek!
Čekání na vstup uživatele
Výše jsem již zmínil pár možností, jak požádat ve skriptu uživatele o vstup. Proberme si všechny znovu a po pořádku.
Pauza (aka „Stiskni libovolnou klávesu“)
Pokud skript musí počkat na to, aby uživatel potvrdil pokračování, slouží k tomu funkce pause:
echo Tento skript zpracuje zadané soubory... pause //vypíše: Tento skript zpracuje zadané soubory... Pro pokračování stiskněte libovolnou klávesu
Funkce sama vypíše text, který radí uživateli, co má udělat. Často se ale používá to, že tento text skryjete a místo něj použijete nějaký vlastní; např.:
echo Tento skript zpracuje zadané soubory... (pro pokračování stiskni libovolnou klávesu) pause > NUL
echo Používáním toho skriptu souhlasíte s podmínkami uvedenými v license.txt echo Pokud souhlasíte, stiskněte libovolnou klávesu. echo Pokud nesouhlasíte, zavřete toto okno kliknutím na [X] nebo stiskem CTRL+C nebo ALT+F4. pause > NUL
Pauza s dobou čekání
Alternativou k příkazu pause je příkaz timeout, který umožňuje zadat čas, po který skript čeká a následně bude automaticky pokračovat. Toto se hodí v případě, že chcete uživateli zobrazit nějaký výsledek (který by jinak mohl zaniknout v ostatních výpisech skriptu), ale nechcete skript blokovat trvale, pokud uživatel skript např. minimalizoval okno skriptu nebo odešel od PC.
První možnost je nastavit čas, po kterém bude skript sám pokračovat, a zároveň umožnit uživateli čekání urychlit:
timeout /T 10 //Vypíše: Waiting for 10 seconds, press a key to continue...
Příkaz aktualizuje uvedený čas, ale bohužel nemá text přeložený do češtiny.
Pokud potřebujete skript pozastavit na pevnou dobu bez možnosti předčasného přerušení (pokračování), přidejte parametr /nobreak:
timeout /T 10 /nobreak //Vypíše: Waiting for 10 seconds, press CTRL+C to quit...
I u tohoto příkazu můžete skrýt výstup, ale přijdete o odpočet:
echo Skript musí nyní počkat 10 sekund na dokončení operace (vyčištění cache apod.)... timeout /t 10 /nobreak > NUL
Zadání libovolného vstupu
Jak bylo uvedeno výše, můžete požádat uživatele o zadání libovolného textu, který se následně uloží do proměnné.
set /P filename=Zadejte jméno souboru: set value=5 set /P value=Zadejte hodnotu 0 až 9 (výchozí: 5):
Výběr z možností
Pokud chcete umožnit uživateli vybrat jednu z možností, ale nechcete mu nechat možnost vybrat neexistující hodnotu (např. v předchozím příkladu nic nebrání uživateli zadat „10“ nebo „X“ i když žádáte o číslo mezi 0 a 9.
Příkaz choice („výběr„, čti „čojs„) umožňuje vytvořit výběr z předem určených hodnot:
choice /C an /M "Chcete pokračovat?" //Vypíše "Chcete pokračovat? [A, N]" choice /C 0123456789 /N /M "Zadejte hodnotu 0 až 9: " choice /C mzx /N /M "Zvolte pohlaví: M = muž, Z = žena, X = ostatní/neurčeno"
Parametr /C (choices, možnosti) určuje klávesy, které může uživatel stisknout. Povolené a doporučené jsou pouze písmena A-Z a číslice 0-9. Parametr /M (message, zpráva) určuje text, který se vypíše. Parametr /N (no choices, bez možností) skryje zobrazení povolených možností – ty pak můžete lépe popsat ve zprávě.
Příkaz choice nabízí i možnost čekat jen určitou dobu a pak vybrat zvolenou hodnotu. Oba parametry /T (timeout) a /D (default) jsou povinné:
choice /C an /M "Chcete pokračovat" /T 10 /D a //Vypíše "Chcete pokračovat [A, N]? //Po 10 sekundách automaticky vybere "A" choice /C 123456789 /N /M "Zadejte hodnotu 1 až 9 (výchozí 5): " /T 10 /D 5 //Po 10 sekundách automaticky zvolí "5"
Po výběru možnosti se hodnota uloží do proměnné ERRORLEVEL jako číslo určující pořadí zvolené možnosti (např. z [A, N] je A = 1 a N = 2). Kontrolu, jakou klávesu uživatel stiskl, můžete provést dvě způsoby; prvním je IF ERRORLEVEL:
choice /C an /M "Chcete zpracovat %1?" if ERRORLEVEL 2 goto skip process %1 :skip //Alternativně bez goto choice /C na /M "Chcete zpracovat %1? [A, N]" /N if ERRORLEVEL 2 process %1 choice /C 123456789 /N /M "Zadejte hodnotu 1 až 9 (výchozí 5): " /T 10 /D 5 if ERRORLEVEL 9 goto do_9 if ERRORLEVEL 8 goto do_8 if ERRORLEVEL 7 goto do_7 if ERRORLEVEL 6 goto do_6 if ERRORLEVEL 5 goto do_5 if ERRORLEVEL 4 goto do_4 if ERRORLEVEL 3 goto do_3 if ERRORLEVEL 2 goto do_2 if ERRORLEVEL 1 goto do_1
První možnost vyžaduje, abyste test dělali s sestupném pořadí. Druhá možnost to nevyžaduje:
choice /C 123 /N /M "Zvolte možnost 1 až 3: " if [1] == [%ERRORLEVEL%] goto do_1 if [2] == [%ERRORLEVEL%] goto do_2 if [3] == [%ERRORLEVEL%] goto do_3
Pozor na to, že pokud byste místo goto zavolali příkaz nebo funkci, přepíše se tím hodnota ERRORLEVEL a může to způsobit výběr více možností současně!
Příkaz choice má ještě jednu skrytou volbu, na kterou byste neměli zapomínat. Pokud uživatel stiskne CTRL+C, bude ERRORLEVEL nastaven na 0:
choice /C 123 /N /M "Zvolte možnost 1 až 3: " if ERRORLEVEL 3 goto do_3 if ERRORLEVEL 2 goto do_2 if ERRORLEVEL 1 goto do_1 if ERRORLEVEL 0 goto do_nothing //alternativní zápis: choice /C 123 /N /M "Zvolte možnost 1 až 3: " if ERRORLEVEL 3 goto do_3 if ERRORLEVEL 2 goto do_2 if ERRORLEVEL 1 goto do_1 goto do_nothing
Volání funkcí v Batch
MS-DOS používal GOTO-LABEL model pro řízení běhu skriptu Batch:
if %1 == %2 goto equal :continue ... exit /b :equal ... goto continue
Funkce s parametry
Windows Console tuto funkčnost zachovává a navíc ji rozšiřuje o to, že label se nemusí chovat jen jako označení místa ve skriptu, ale zároveň definuje jméno funkce, kterou pak můžete zavolat funkcí call:
if %1 == %2 call :equal %2 %1 %1.orig ... exit /b :equal del %1 ren %2 %3 exit /b
Pokud chcete použít label jako funkci, musíte dodržet několik pravidel:
- při volání používáte příkaz
CALL(stejně jako pro volání jiného skriptu), ale musíte použít dvojtečku pro označení, že jde o jméno funkce (na rozdíl odgoto, kde je dvojtečka nepovinná) - hodnoty
%1,%2, atd. vrací parametry funkce, nikoliv původní parametry Batch skriptu (%~1,%~2, atd. vrací parametry funkce bez uvozovek). Hodnoty %0 obsahuje jméno funkce (vč. dvojtečky), nikoliv jméno skriptu - funkci je potřeba ukončit příkazem
endlocalneboexit /bnebogoto :EOF(kde dvojtečka je povinná!). V opačném případě se funkce ukončí, až dojde skript na konec souboru a následně bude pokračovat od místa volání funkce (což je obvykle nežádoucí). - proměnné vytvořené příkazem
SETjsou sdílené mezi funkcí a hlavním skriptem
Funkce s nekonečným počtem parametrů
Funkce může použít SHIFT a GOTO k tomu, aby restartovala sama sebe a zpracovala všechny parametry bez nutnosti je rekurzovně předávat sama sobě:
call :process %* goto :EOF :process process %1 shift if not [] == [%1] goto process exit /b
Všimněte si, že funkci můžeme předat všechny parametry skript pomocí %*.
Příkaz SHIFT uvnitř funkce posouvá parametry funkce. Nijak nemění parametry skriptu. Pozor na to, že SHIFT posune %1 do %0, takže pak již není možno přečíst jméno funkce!!!
Příkaz goto je možno z funkce používat obvyklým způsobem. Můžete skočit na konkrétní místo funkce (ať už dopředu nebo zpět), můžete z funkce vyskočit a pak se vrátit zpět, apod.
Návratová hodnota funkce
Batch funkce může vrátit číselnou hodnotu, která se následně uloží do proměnné ERRORLEVEL. Tu je pak možno použít k dalšímu podmíněnému zpracování. Pokud potřebujete vrátit něco jiného než číslo, můžete vytvořit proměnnou.
call :copy %* if 0 == %ERRORLEVEL% echo Nic nebylo zkopírováno!!! if 1 == %ERRORLEVEL% echo Byl zkopírován jeden soubor. if 2 == %ERRORLEVEL% echo Byly zkopírovány dva soubory, %1 a %2. if 3 == %ERRORLEVEL% echo Byly zkopírovány tři soubory, %1, %2 a %3. if 4 == %ERRORLEVEL% echo Byly zkopírovány čtyři soubor, %1, %2, %3 a %4. if 4 LSS %ERRORLEVEL% echo Bylo zkopírováno %ERRORLEVEL% souborů, od %1 po %last%. goto :EOF :copy set counter=0 :start if [] == [%1] exit /B %counter% if exist %1 copy %1 "%~n1.bak" set /A counter=%counter% + 1 set last=%1 shift goto start
Uvedený skript zkopíruje všechny soubory do *.bak a následně zobrazí zprávu o tom, kolik souborů bylo zpracováno a jaké (přičemž řeší problém s češtinou, která používá pro 1, 2 až 4 a pro 5 a více položek jiné koncovky). Pro 5 a více souborů pak vypíše jen jména prvního (který je stále uložen v prvním parametru skriptu, i když jsme používali SHIFT ve funkci) a posledního souboru (který jsme si uložili do proměnné %last%).
Všimněte si, že u příkazu SET používáme parametr /A, který zapíná podporu aritmetických operací, abysme tak spočetli, kolik souborů bylo zpracováno a následně tuto informaci předáváme zpět z funkce.
Podmínky
Ve skriptech můžete používat celou řadu podmínek. Základní pravidlo je, že za každou podmínkou může následovat jen jeden příkaz. Pokud tedy chcete proévst více příkazů, musíte buď podmínku opakovat na každé řádce, nebo musíte skript přesměrovat jinam (goto, volání funkce, volání jiného skriptu).
Porovnání
Základní podmínka je porovnání dvou hodnot pomocí if a == b. Obvykle jedna je proměnná a druhá je statická hodnota, ale mohou být obě proměnné.
Pozor na to, že vyhodnocení podmínky probíhá tak, že nejprve se proměnná přeloží na hodnotu a pak teprve se provede srovnání. Pokud je ale proměnná prázdná, vytvoří to nevalidní příkaz a skript selže. Proměnné je tedy potřeba obalit do uvozovek, nebo do hranatých závorek:
rem vhodné, pokud víte, že proměnná neobsahuje uvozovky
if "a" == "%value%" goto a
rem lepší, pokud nevíte, jestli proměnná neobsahuje uvozovky
if [a] == [%value%] goto a
rem pro parametr použijte vlnovku, která uvozovky odstraní
if [a] == [%~1] goto a
Pokud naopak chcete zjistit, jestli se hodnoty liší, použijte if not a == b:
if not [] == [%~1] goto process
Pokud potřebujete provést „else“ podmínku, můžete použít if a pak if not nebo použít dvě goto:
if [%a%] == [%b%] set result=equal
if not [%a%] == [%b%] set result=not equal
if [%a%] == [%b%] goto equal
goto not_equal
:equal
set result=equal
goto skip_result
:not_equal
set result=not equal
:skip_result
rem V případě proměnných stačí nastavit "else" hodnotu a pak ověřit podmínku:
set result=not equal
if [%a%] == [%b%] set result=equal
Pokud porovnáváte řetězce, můžete připat parametr /i pro vypnutí kontroly velikosti písmen. Ve Windows se to hodí k tomu, že jména souborů také ignorují velikost písmen:
rem Bude fungovat i pro Input.TXT
if /i [input.txt] == [%~1] goto process input.txt
Existence souboru
Pomocí podmínky if exist file můžete ověřit, jestli na disku existuje soubor (nebo složka) nebo ne (podmínka if not exist file). To se obvykle hodí k ověření, jestli ho můžete otevřít (či smazat), nebo naopak jestli je potřeba ho vytvořit.
if exist input.txt process input.txt
if exist result.tmp del result.tmp
if not exist "%~1" echo Zadaný soubor neexistuje
if not exist output.txt prepare -in input.txt -out output.txt
Existence proměnné
Podmínka if defined value může ověřit existenci proměnné stejně, jako if exist file ověřuje soubory. Důležité je si uvědomit, že pokud proměnná neexistuje, nemůže nic vytisknout a proto není možné použít .if defined %value%
Ověření existence se obvykle používá k tomu, aby se nastavila hodnota, která ještě neexistuje, takže se často používá ve formě if not defined value:
:start
if [] == [%1] goto end
if not defined quality set /P quality=Set compression quality:
compress -q %quality% %1
shift
goto start
:end
echo Done
pause > NUL
Proměnnou můžete zrušit tím, že do ní přiřadíte práznou hodnotu – pozor na to, aby v souboru za rovnítkem nenásledovala mezera či jiný neviditelný znak (kromě nové řádky):
:start
if [] == [%1] goto end
if not defined quality set /P quality=Set compression quality:
compress -q %quality% %1
if errorlevel 1 goto fail
shift
goto start
:fail
echo Invalid compression quality, try different one...
rem remove invalid quality and ask for it again
set quality=⏎
rem no SHIFT here process same file again
goto start
:end
echo Done
pause > NUL
Porovnávání hodnot
Číselné hodnoty můžete porovnávat, jestli jsou větší nebo menší pomocí if a <operátor> b. Použitelné operátory jsou:
EQU= rovná se (odpovídá ==)NEQ= nerovná se (odpovídánot ==)LSS= je menší než (<)LEQ= je menší nebo se rovná (<=)GTR= je větší než (>) (Pozor že je to GreaTeR a ne GReaTer!)GEQ= je větší nebo se rovná (>=)
Podmínky s čísly je možno řetězit pomocí goto, pokud je správně seřadíte:
if %value% LEQ 0 goto zero_or_less
if %value% == 1 goto one
if %value% LSS 5 goto two_to_four
if %value% GEQ 10 goto ten_or_more
goto six_to_nine
Porovnávání větší/menší funguje číselně pouze pokud jsou obě hodnoty (celá) čísla. Pokud je některý s operandů řetězec, porovnávají se hodnoty bytově. To platí i v případě, že hodnoty jsou čísla s desetinnou částí. Toho se dá využít k porovnání desetinných čásel:
> IF a LSS b echo Menší
Menší
> IF 1.4 LSS 1.5 echo Menší
Menší
> IF 1.6 LSS 1.5 echo Menší
//nic nevytiskne, 1.6 není menší než 1.5
Výsledek příkazu
Některé příkazy nebo programy mohou vrátit číselnou hodnotu. Obvykle 0 znamená úspěch a vyšší hodnoty označují chybu. Jaké a jestli příkaz nebo program vrací hodnotu najdete v jeho nápovědě (nebo prostě můžete zkusit co vrací).
Výsledek posledního příkazu ověříte podmínkou if ERRORLEVEL X. Jelikož to není proměnná a spuštění dalšího příkazu výsledek přepíše, je potřeba používat goto:
process input.txt
if ERRORLEVEL 0 goto success
if ERRORLEVEL 1 goto error
if ERRORLEVEL 2 goto warning
goto other_error
Pokud chcete výsledek příkazu vytisknout nebo uložit na později, můžete místo podmínky if ERRORLEVEL použít proměnnou %errorlevel%:
process input.txt
echo Proces skončil s hodnotou %errorlevel%.
set result=%errorlevel%
Podmínka AND
Pokud potřebujete ověřit dvě podmínky zároveň, není k dispozici operátor AND nebo &&, ale můžete za podmínku zadat jako příkaz další podmínku:
if exist input.txt if not exist output.txt process -in input.txt -out output.txt
Výpis obsahu aktuálního adresáře do textového souboru s názvem „seznam.txt“:
chcp 1250dir * /b /o:n /d > seznam.txt