すべてのシステム管理者は、おそらく何年にもわたって学んだスキルを持っており、「それが私の世界を変えた」と指摘して言うことができます。そのスキル、またはそのビットの情報、またはそのテクニックは、私が物事を行う方法を変えました。私たちの多くにとって、それはループです。 バッシュで。確かにより堅牢またはスケーラブルな自動化へのアプローチは他にもあります。それらのほとんどは、for
のシンプルさとすぐに使える使いやすさに匹敵しません。 ただし、ループします。
何千ものシステムの構成を自動化したい場合は、おそらくAnsibleを使用する必要があります。ただし、1,000個のファイルの名前を変更しようとしている場合、または同じコマンドを複数回実行しようとしている場合は、for
ループは間違いなくその仕事に適したツールです。
[次のこともお勧めします:AnsibleでJinjaテンプレートを使用してループをマスターする]
プログラミングまたはスクリプトのバックグラウンドがすでにある場合は、for
に精通している可能性があります。 ループはありません。そうでない場合は、わかりやすい英語で分解してみます。
基本的な概念は次のとおりです。FOR 特定のアイテムのセット、実行 事。
指定されたアイテムのセットは、文字通りのオブジェクトのセット、またはBashがリストに推定できるものであれば何でもかまいません。たとえば、ファイルから取得したテキスト、別のBashコマンドの出力、コマンドラインから渡されたパラメータなどです。このループ構造をBashスクリプトに変換することも簡単です。この記事では、for
の例をいくつか紹介します。 ループを使用すると、コマンドラインヒーローのように見せることができます。次に、それらの例をいくつか取り上げて、より構造化されたBashスクリプト内に配置します。
forループの基本構造
まず、for
の基本構造について説明しましょう。 ループしてから、いくつかの例を見ていきます。
for
の基本構文 ループは次のとおりです:
for <variable name> in <a list of items>;do <some command> $<variable name>;done;
変数名 do
で指定する変数になります セクションが表示され、ループ内のアイテムが含まれます。
アイテムのリスト スペースまたは改行で区切られたリストを返すものであれば何でもかまいません。
次に例を示します:
$ for name in joey suzy bobby;do echo $name;done
それは簡単で、それほど多くのことは行われていませんが、それで始められます。変数$name ループが現在動作しているリスト内のアイテムが含まれ、do
内の1つまたは複数のコマンドが含まれます セクションが実行されると、ループは次のアイテムに移動します。ループごとに複数のアクションを実行することもできます。 do
の間のすべて およびdone
実行されます。新しいコマンドには;
が必要です それらを区切る。
$ 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
さて、いくつかの本物 例。
ファイルの名前変更
このループは、Bashコマンドの出力を受け取りますls *.pdf
返された各ファイル名に対してアクションを実行します。この場合、今日の日付をファイル名の最後に追加します(ただし、ファイル拡張子の前に追加します)。
for i in $(ls *.pdf); do
mv $i $(basename $i .pdf)_$(date +%Y%m%d).pdf
done
説明のために、これらのファイルを含むディレクトリでこのループを実行します。
file1.pdf
file2.pdf
...
fileN.pdf
ファイルの名前は次のように変更されます:
file1_20210210.pdf
file2_20210210.pdf
...
fileN_20210210.pdf
何百ものファイルがあるディレクトリでは、このループにより、すべてのファイルの名前を変更する時間を大幅に節約できます。
アイテムのリストの外挿
scp
したいファイルがあると想像してください。 複数のサーバーに。 for
を組み合わせることができることを忘れないでください シェル拡張などの他のBash機能とループします。これにより、Bashは一連のアイテムのリストを拡張できます。これは、文字と数字に対して機能します。例:
$ echo {0..10}
0 1 2 3 4 5 6 7 8 9 10
サーバーにweb0のようなパターンで名前が付けられていると仮定します。 、 web1 、 web2 、 web3 、Bashに次のように一連の数値を反復させることができます:
$ for i in web{0..10};do scp somefile.txt ${i}:;done;
これはweb0を反復処理します 、 web1 、 web2 、 web3 、など、各アイテムに対してコマンドを実行します。
いくつかの反復を定義することもできます。例:
$ 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
反復を組み合わせることもできます。米国とカナダに2つのデータセンターがあり、サーバーの命名規則によって、サーバーのHAペアが存在するデータセンターが特定されているとします。たとえば、 web-us-0 web-ca-0 は、米国のデータセンターで最初のWebサーバーになります。 Web0のになります CAデータセンターのカウンターパート。両方のシステムで何かを実行するには、次のようなシーケンスを使用できます。
$ 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
サーバー名を簡単に繰り返すことができない場合は、名前のリストをfor
に提供できます。 ループ:
$ 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
ネスト
これらのアイデアのいくつかを組み合わせて、より複雑なユースケースにすることもできます。たとえば、前の例で使用した番号付きの命名規則に従って、ファイルのリストをWebサーバーにコピーするとします。
これは、ネストされたループを介して最初のリストに基づいて2番目のリストを繰り返すことで実現できます。ワンライナーとしてやっていると、これを理解するのは少し難しくなりますが、間違いなく行うことができます。ネストされたfor
ループは、親のfor
の反復ごとに実行されます ループ。ループごとに異なる変数名を指定してください。
ファイルのリストをコピーするにはfile1.txt、file2.txt、 およびfile3.txt Webサーバーに対して、このネストされたループを使用します:
$ 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
よりクリエイティブな名前の変更
これを行うには他の方法もあるかもしれませんが、これはできることの単なる例であることを忘れないでください for
で行う ループ。 FILE002.txtのような名前のファイルが山ほどある場合はどうなりますか 、およびファイルを置き換えたい TEXTのようなもので 。 Bash自体に加えて、sed
などの他のオープンソースツールも自由に使用できることを忘れないでください。 、grep
、 もっと。これらのツールをfor
と組み合わせることができます このようにループします:
$ 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
Bashスクリプトにforループを追加する
for
を実行しています コマンドラインで直接ループすることは素晴らしいことであり、いくつかのタスクのためにかなりの時間を節約します。さらに、for
を含めることができます パワー、読みやすさ、柔軟性を高めるために、Bashスクリプトの一部としてループします。
たとえば、次のように、ネストされたループの例をBashスクリプトに追加して、読みやすさを向上させることができます。
$ 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
このスクリプトを保存して実行すると、上記のネストされたループの例を実行した場合と同じ結果になりますが、読みやすくなり、変更や保守も簡単になります。
$ bash copy_web_files.sh
Copying file1 to server web0
Copying file1 to server web1
... TRUNCATED ...
Copying file3 to server web3
for
の柔軟性と再利用性を高めることもできます パラメータ入力を可能にするBashスクリプトにそれらを含めることによってループします。たとえば、例のようにファイルの名前を変更するにはよりクリエイティブな名前変更 上記でユーザーが名前の接尾辞を指定できるようにするには、次のスクリプトを使用します:
$ 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
このスクリプトでは、ユーザーは最初のパラメーターとしてソースファイルのプレフィックス、2番目のパラメーターとしてファイルのサフィックス、3番目のパラメーターとして新しいプレフィックスを指定します。たとえば、 FILEで始まるすべてのファイルの名前を変更するには 、タイプ .txt テキストへ 、次のようなスクリプトを実行します:
$ 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
これは元の例と似ていますが、ユーザーが他のパラメーターを指定してスクリプトの動作を変更できるようになりました。たとえば、 TEXTで始まるすべてのファイルの名前を変更するには 新規へ 、以下を使用してください:
$ 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
[無料コース:仮想化とインフラストラクチャの移行の技術概要。 ]
結論
うまくいけば、これらの例はfor
の力を示しています Bashコマンドラインでループします。ループを使用すると、実際に多くの時間を節約し、エラーが発生しにくい方法でタスクを実行できます。ただ注意してください。ループは、論理ボリュームや仮想ディスクの作成(または削除)など、誤って破壊的なことをするように依頼した場合でも、依頼したとおりに実行されます。
Bashがfor
であることを願っています ループは、私たちの世界を変えたのと同じようにあなたの世界を変えます。