Tipy a triky pro Příkazový řádek (Windows Console) a Batch

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.

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:

  • %~1 vrátí první parametr jak je, jen odstraní uvozovky
  • %~f1 vrátí plné jméno (fullname) souboru včetně cesty
  • %~n1 vrátí jen jméno souboru (name) bez cesty a přípony
  • %~x1 vrátí příponu souboru (s tečkou; např. „.txt„)
  • %~d1 vrátí písmeno disku, na kterém je soubor (např. C:)
  • %~p1 vrátí cestu k souboru v unix formátu (např. \path\)
  • %~dp1 vrátí cestu k souboru včetně disku (např. C:\path\)
  • %~nx1 vrátí jméno souboru s příponou (např. file.txt)
  • %~dpn1 vrá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.
  • %~a1 vrátí atributy souboru
  • %~t1 vrátí čas vytvoření souboru
  • %~z1 vrátí velikost souboru
  • %~ $PATH:1 zkusí 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

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ů.

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 od goto, 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 endlocal nebo exit /b nebo goto :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 SET jsou 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.

Jedna myšlenka na “Tipy a triky pro Příkazový řádek (Windows Console) a Batch”

  1. Výpis obsahu aktuálního adresáře do textového souboru s názvem „seznam.txt“:

    chcp 1250
    dir * /b /o:n /d > seznam.txt

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *

Tato stránka používá Akismet k omezení spamu. Podívejte se, jak vaše data z komentářů zpracováváme..