Každý správce systému má pravděpodobně nějakou dovednost, kterou se za ta léta naučil, na kterou může ukázat a říct:"To změnilo můj svět." Ta dovednost, nebo ten kousek informací nebo ta technika prostě změnily, jak věci dělám. Pro mnohé z nás je to zacyklení v Bash. Existují další přístupy k automatizaci, které jsou jistě robustnější nebo škálovatelnější. Většina z nich se nevyrovná jednoduchosti a snadné použitelnosti for
smyčka.
Pokud chcete automatizovat konfiguraci tisíců systémů, měli byste pravděpodobně použít Ansible. Pokud se však pokoušíte přejmenovat tisíc souborů nebo provést stejný příkaz několikrát, pak for
smyčka je rozhodně tím správným nástrojem pro tuto práci.
[ Také by se vám mohlo líbit: Ovládání smyček pomocí šablon Jinja v Ansible ]
Pokud již máte zkušenosti s programováním nebo skriptováním, pravděpodobně víte, k čemu for
smyčky ano. Pokud nejste, pokusím se to pro vás rozebrat v jednoduché angličtině.
Základní koncept je:PRO danou sadu položek, DO věc.
Daná sada položek může být doslovná sada objektů nebo cokoli, co může Bash extrapolovat na seznam. Například text vytažený ze souboru, výstup jiného příkazu Bash nebo parametry předávané přes příkazový řádek. Převod této struktury smyčky na Bash skript je také triviální. V tomto článku vám ukážeme několik příkladů for
smyčka může způsobit, že budete vypadat jako hrdina příkazového řádku, a poté vezmeme některé z těchto příkladů a vložíme je do strukturovanějšího skriptu Bash.
Základní struktura cyklu for
Nejprve si promluvme o základní struktuře for
smyčka, a pak se pustíme do několika příkladů.
Základní syntaxe for
smyčka je:
for <variable name> in <a list of items>;do <some command> $<variable name>;done;
Název proměnné bude proměnná, kterou zadáte v do
a bude obsahovat položku ve smyčce, ve které se nacházíte.
seznam položek může být cokoli, co vrátí seznam oddělený mezerou nebo novým řádkem.
Zde je příklad:
$ for name in joey suzy bobby;do echo $name;done
Je to tak jednoduché, jak to jen jde, a neděje se toho moc, ale pomůže vám to začít. Proměnná $name bude obsahovat položku v seznamu, se kterou smyčka aktuálně pracuje, a jakmile příkaz (nebo příkazy) v do
provedete, smyčka se přesune na další položku. Můžete také provést více než jednu akci na smyčku. Cokoli mezi do
a done
bude popraven. Nové příkazy potřebují pouze ;
vymezující je.
$ for name in joey suzy bobby; do echo first $name;echo second $name;done;
first joey
second joey
first suzy
second suzy
first bobby
second bobby
Teď něco skutečného příklady.
Přejmenování souborů
Tato smyčka přebírá výstup příkazu Bash ls *.pdf
a provede akci s každým vráceným názvem souboru. V tomto případě přidáváme dnešní datum na konec názvu souboru (ale před příponu souboru).
for i in $(ls *.pdf); do
mv $i $(basename $i .pdf)_$(date +%Y%m%d).pdf
done
Pro ilustraci spusťte tuto smyčku v adresáři obsahujícím tyto soubory:
file1.pdf
file2.pdf
...
fileN.pdf
Soubory budou přejmenovány takto:
file1_20210210.pdf
file2_20210210.pdf
...
fileN_20210210.pdf
V adresáři se stovkami souborů vám tato smyčka ušetří značné množství času při přejmenování všech z nich.
Extrapolace seznamů položek
Představte si, že máte soubor, který chcete scp
na několik serverů. Pamatujte, že můžete kombinovat for
smyčka s dalšími funkcemi Bash, jako je expanze shellu, která umožňuje Bash rozšířit seznam položek, které jsou v sérii. To může fungovat pro písmena a čísla. Například:
$ echo {0..10}
0 1 2 3 4 5 6 7 8 9 10
Za předpokladu, že jsou vaše servery pojmenovány podle nějakého vzoru, jako je web0 , web1 , web2 , web3 , můžete nechat Bash iterovat řadu čísel takto:
$ for i in web{0..10};do scp somefile.txt ${i}:;done;
Toto bude iterováno přes web0 , web1 , web2 , web3 , a tak dále, provedením vašeho příkazu pro každou položku.
Můžete také definovat několik iterací. Například:
$ for i in web{0..10} db{0..2} balance_{a..c};do echo $i;done
web0
web1
web2
web3
web4
web5
web6
web7
web8
web9
web10
db0
db1
db2
balance_a
balance_b
balance_c
Můžete také kombinovat iterace. Představte si, že máte dvě datová centra, jedno ve Spojených státech a další v Kanadě, a konvence pojmenování serveru určuje, ve kterém datovém centru žil pár serverů HA. Například web-us-0 by byl prvním webovým serverem v datovém centru v USA, zatímco web-ca-0 by byly webové 0 protějšek v datovém centru CA. Chcete-li provést něco na obou systémech, můžete použít sekvenci jako je tato:
$ for i in web-{us,ca}-{0..3};do echo $i;done
web-us-0
web-us-1
web-us-2
web-us-3
web-ca-0
web-ca-1
web-ca-2
web-ca-3
V případě, že názvy vašich serverů nelze snadno iterovat, můžete poskytnout seznam názvů do for
smyčka:
$ cat somelist
first_item
middle_things
foo
bar
baz
last_item
$ for i in `cat somelist`;do echo "ITEM: $i";done
ITEM: first_item
ITEM: middle_things
ITEM: foo
ITEM: bar
ITEM: baz
ITEM: last_item
Vnoření
Některé z těchto nápadů můžete také kombinovat pro složitější případy použití. Představte si například, že chcete na své webové servery zkopírovat seznam souborů, které se řídí konvencí číslování, kterou jste použili v předchozím příkladu.
Můžete toho dosáhnout opakováním druhého seznamu založeného na prvním seznamu prostřednictvím vnořených smyček. To je trochu těžké sledovat, když to děláte jako jednovrstvé, ale určitě to lze udělat. Vaše vnořené for
smyčka se provede při každé iteraci nadřazeného for
smyčka. Nezapomeňte zadat různé názvy proměnných pro každou smyčku.
Chcete-li zkopírovat seznam souborů soubor1.txt, soubor2.txt, a file3.txt k webovým serverům použijte tuto vnořenou smyčku:
$ for i in file{1..3};do for x in web{0..3};do echo "Copying $i to server $x"; scp $i $x; done; done
Copying file1 to server web0
Copying file1 to server web1
Copying file1 to server web2
Copying file1 to server web3
Copying file2 to server web0
Copying file2 to server web1
Copying file2 to server web2
Copying file2 to server web3
Copying file3 to server web0
Copying file3 to server web1
Copying file3 to server web2
Copying file3 to server web3
Další přejmenování kreativ
Mohou existovat i jiné způsoby, jak toho dosáhnout, ale pamatujte, že toto je pouze příklad toho, co můžete proveďte pomocí for
smyčka. Co když máte horu souborů pojmenovaných něco jako FILE002.txt? a chcete nahradit FILE s něčím jako TEXT . Pamatujte, že kromě samotného Bash máte k dispozici také další open source nástroje, jako je sed
, grep
, a více. Tyto nástroje můžete kombinovat s for
smyčka, jako je tato:
$ ls FILE*.txt
FILE0.txt FILE10.txt FILE1.txt FILE2.txt FILE3.txt FILE4.txt FILE5.txt FILE6.txt FILE7.txt FILE8.txt FILE9.txt
$ for i in $(ls FILE*.txt);do mv $i `echo $i | sed s/FILE/TEXT/`;done
$ ls FILE*.txt
ls: cannot access 'FILE*.txt': No such file or directory
$ ls TEXT*.txt
TEXT0.txt TEXT10.txt TEXT1.txt TEXT2.txt TEXT3.txt TEXT4.txt TEXT5.txt TEXT6.txt TEXT7.txt TEXT8.txt TEXT9.txt
Přidání smyčky for do skriptu Bash
Spuštění for
smyčky přímo na příkazovém řádku je skvělé a ušetří vám to značné množství času na některé úkoly. Kromě toho můžete zahrnout for
smyčky jako součást vašich Bash skriptů pro vyšší výkon, čitelnost a flexibilitu.
Příklad vnořené smyčky můžete například přidat do skriptu Bash, abyste zlepšili jeho čitelnost, takto:
$ vim copy_web_files.sh
# !/bin/bash
for i in file{1..3};do
for x in web{0..3};do
echo "Copying $i to server $x"
scp $i $x
done
done
Když uložíte a spustíte tento skript, výsledek je stejný jako při spuštění výše uvedeného příkladu vnořené smyčky, ale je čitelnější a navíc se snáze mění a udržuje.
$ bash copy_web_files.sh
Copying file1 to server web0
Copying file1 to server web1
... TRUNCATED ...
Copying file3 to server web3
Můžete také zvýšit flexibilitu a opětovnou použitelnost vašeho for
smyčky jejich zahrnutím do skriptů Bash, které umožňují zadávání parametrů. Chcete-li například přejmenovat soubory jako v příkladu Další kreativní přejmenování výše umožňuje uživateli zadat příponu názvu, použijte tento skript:
$ vim rename_files.sh
# !/bin/bash
source_prefix=$1
suffix=$2
destination_prefix=$3
for i in $(ls ${source_prefix}*.${suffix});do
mv $i $(echo $i | sed s/${source_prefix}/${destination_prefix}/)
done
V tomto skriptu uživatel zadá předponu zdrojového souboru jako první parametr, příponu souboru jako druhý a novou předponu jako třetí parametr. Chcete-li například přejmenovat všechny soubory začínající FILE , typu .txt na TEXT , spusťte skript takto:
$ ls FILE*.txt
FILE0.txt FILE10.txt FILE1.txt FILE2.txt FILE3.txt FILE4.txt FILE5.txt FILE6.txt FILE7.txt FILE8.txt FILE9.txt
$ bash rename_files.sh FILE txt TEXT
$ ls TEXT*.txt
TEXT0.txt TEXT10.txt TEXT1.txt TEXT2.txt TEXT3.txt TEXT4.txt TEXT5.txt TEXT6.txt TEXT7.txt TEXT8.txt TEXT9.txt
Toto je podobné původnímu příkladu, ale nyní mohou vaši uživatelé zadat další parametry pro změnu chování skriptu. Chcete-li například přejmenovat všechny soubory, které nyní začínají TEXT na NOVÉ , použijte následující:
$ bash rename_files.sh TEXT txt NEW
$ ls NEW*.txt
NEW0.txt NEW10.txt NEW1.txt NEW2.txt NEW3.txt NEW4.txt NEW5.txt NEW6.txt NEW7.txt NEW8.txt NEW9.txt
[ Bezplatný kurz pro vás:Technický přehled virtualizace a migrace infrastruktury. ]
Závěr
Doufejme, že tyto příklady demonstrovaly sílu for
smyčka na příkazovém řádku Bash. Pomocí smyček můžete skutečně ušetřit spoustu času a provádět úkoly způsobem, který je méně náchylný k chybám. Jen buď opatrný. Vaše smyčky udělají to, o co je požádáte, i když je požádáte, aby udělaly něco destruktivního náhodou, jako je vytvoření (nebo smazání) logických svazků nebo virtuálních disků.
Doufáme, že Bash for
smyčky změní váš svět stejně, jako změnily náš.