GNU/Linux >> Linux の 問題 >  >> Linux

Bashでループを作成する方法

人々がUnixシェルを学びたいと思う一般的な理由は、バッチ処理の力を解き放つことです。多くのファイルに対して一連のアクションを実行する場合、それを実行する方法の1つは、それらのファイルを反復処理するコマンドを作成することです。プログラミング用語では、これは実行制御と呼ばれます。 その最も一般的な例の1つは、 for ループ。

for ループは、コンピュータに実行させたいアクションの詳細を示すレシピです。 指定する各データオブジェクト(ファイルなど)。

クラシックなforループ

Linuxターミナル

  • Linux用の上位7つのターミナルエミュレータ
  • Linuxでのデータ分析のための10個のコマンドラインツール
  • 今すぐダウンロード:SSHチートシート
  • 高度なLinuxコマンドのチートシート
  • Linuxコマンドラインチュートリアル

簡単に試すことができるループは、ファイルのコレクションを分析するループです。これは、それ自体ではおそらく有用なループではありませんが、ディレクトリ内の各ファイルを個別に処理できることを自分自身に証明するための安全な方法です。まず、ディレクトリを作成し、そこにいくつかのファイルのコピーを配置して、簡単なテスト環境を作成します。最初はどのファイルでもかまいませんが、後の例ではグラフィックファイル(JPEG、PNGなど)が必要です。フォルダーを作成し、ファイルマネージャーまたはターミナルを使用してフォルダーにファイルをコピーできます。

$ mkdir example
        $ cp ~/Pictures/vacation/*.{png,jpg} example

ディレクトリを新しいフォルダに変更し、その中のファイルを一覧表示して、テスト環境が期待どおりであることを確認します。

$ cd example
$ ls -1
cat.jpg
design_maori.png
otago.jpg
waterfall.png

ループ内で各ファイルを個別にループする構文は次のとおりです。変数を作成します( f たとえば、ファイルの場合)。次に、変数を循環させるデータセットを定義します。この場合、 * を使用して、現在のディレクトリ内のすべてのファイルを循環します。 ワイルドカード文字( * ワイルドカードはすべてに一致します )。次に、この導入句をセミコロン(; )で終了します。 。

$ for f in * ;

好みに応じて、戻るを押すことを選択できます ここ。構文的に完了するまで、シェルはループを実行しようとしません。

次に、ループの各反復で何を実行するかを定義します。簡単にするために、ファイルを使用してください fで表される各ファイルに関するデータを少し取得するコマンド 変数(ただし、 $が前に付けられます 変数の値を現在含まれている変数と交換するようにシェルに指示するには):

do file $f ;

別のセミコロンで句を終了し、ループを閉じます:

done

戻るを押します すべてを循環するシェルを開始します 現在のディレクトリにあります。 for ループは、各ファイルを1つずつ変数 fに割り当てます。 コマンドを実行します:

$ for f in * ; do
        > file $f ;
        > done
        cat.jpg: JPEG image data, EXIF standard 2.2
        design_maori.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
        otago.jpg: JPEG image data, EXIF standard 2.2
        waterfall.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced

次のように書くこともできます:

$ for f in *; do file $f; done
        cat.jpg: JPEG image data, EXIF standard 2.2
        design_maori.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
        otago.jpg: JPEG image data, EXIF standard 2.2
        waterfall.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced

複数行と単一行の両方の形式はシェルと同じであり、まったく同じ結果を生成します。

実用的な例

これは、ループが日常のコンピューティングにどのように役立つかを示す実際的な例です。友達に送りたい休暇の写真のコレクションがあると仮定します。写真ファイルは巨大であるため、メールで送信するには大きすぎ、写真共有サービスにアップロードするには不便です。写真の小さいWebバージョンを作成したいが、100枚の写真があり、各写真を1枚ずつ減らすことに時間を費やしたくない。

まず、 ImageMagickをインストールします Linux、BSD、またはMacでパッケージマネージャーを使用してコマンドを実行します。たとえば、FedoraとRHELの場合:

$ sudo dnf install ImageMagick

UbuntuまたはDebianの場合:

$ sudo apt install ImageMagick

BSDでは、ポートを使用します またはpkgsrc。 Macでは、HomebrewまたはMacPortsを使用します。

ImageMagickをインストールすると、写真を操作するための一連の新しいコマンドができます。

作成しようとしているファイルの宛先ディレクトリを作成します:

$ mkdir tmp

各写真を元のサイズの33%に縮小するには、次のループを試してください:

$ for f in * ; do convert $f -scale 33% tmp/$f ; done

次に、 tmpを調べます 拡大縮小した写真を表示するフォルダ。

ループ内では任意の数のコマンドを使用できるため、ファイルのバッチに対して複雑なアクションを実行する必要がある場合は、ワークフロー全体を実行の間に配置できます。 および完了 forのステートメント ループ。たとえば、処理された各写真をWebホストの共有写真ディレクトリに直接コピーし、ローカルシステムから写真ファイルを削除するとします。

$ for f in * ; do 
    convert $f -scale 33% tmp/$f
    scp -i seth_web tmp/$f [email protected]:~/public_html
    trash tmp/$f ;
  done

forによって処理されるファイルごとに ループすると、コンピュータは自動的に3つのコマンドを実行します。つまり、この方法で10枚の写真を処理するだけで、30個のコマンドを節約でき、おそらく少なくとも何分も節約できます。

ループを制限する

ループは必ずしもすべてのファイルを調べる必要はありません。サンプルディレクトリ内のJPEGファイルのみを処理したい場合があります:

$ for f in *.jpg ; do convert $f -scale 33% tmp/$f ; done
$ ls -m tmp
cat.jpg, otago.jpg

または、ファイルを処理する代わりに、アクションを特定の回数繰り返す必要がある場合があります。 for ループの変数は、提供するデータによって定義されるため、ファイルの代わりに数値を繰り返すループを作成できます。

{0..4}のnの
$ for n in {0..4}; do echo $n ; done
0
1
2
3
4
より多くのループ

これで、独自のループを作成するのに十分な知識が得られました。ループに慣れるまで、コピーで使用してください。 処理するファイルの名前を変更し、可能な限り多くの場合、セーフガードが組み込まれたコマンドを使用して、データの破損や、ファイルのディレクトリ全体の名前を誤って同じ名前に変更し、それぞれが他のファイルを上書きするなどの修復不可能なミスを防止します。 。

高度なfor トピックをループし、読み進めてください。

すべてのシェルがBashであるとは限りません

for キーワードはBashシェルに組み込まれています。多くの同様のシェルは同じキーワードと構文を使用しますが、tcshなどの一部のシェルは、 foreachなどの異なるキーワードを使用します 、代わりに。

tcshでは、構文は精神的には似ていますが、Bashよりも厳密です。次のコードサンプルでは、​​文字列 foreach?を入力しないでください。 2行目と3行目。これは、ループを構築している途中であることを警告する2番目のプロンプトです。

$ foreach f (*)
foreach? file $f
foreach? end
cat.jpg: JPEG image data, EXIF standard 2.2
design_maori.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
otago.jpg: JPEG image data, EXIF standard 2.2
waterfall.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced

tcshでは、両方の foreach および終了 for を作成できないように、別々の行に単独で表示する必要があります Bashや同様のシェルでできるように1行でループします。

findコマンドを使用したforループ

理論的には、 forを提供しないシェルを見つけることができます ループ機能、または機能が追加された別のコマンドを使用したい場合があります。

検索 コマンドは、 forの機能を実装するもう1つの方法です。 ループは、ループに含めるファイルの範囲と並列処理のオプションを定義するいくつかの方法を提供するためです。

検索 コマンドは、ハードドライブ上のファイルを見つけるのに役立ちます。構文は単純です。検索する場所のパスを指定し、検索します。 すべてのファイルとディレクトリを検索します:

$ find . 
.
./cat.jpg
./design_maori.png
./otago.jpg
./waterfall.png

名前の一部を追加することで、検索結果をフィルタリングできます:

$ find . -name "*jpg"
./cat.jpg
./otago.jpg

検索の優れた点 見つかった各ファイルは、 -execを使用してループにフィードできるということです。 国旗。たとえば、サンプルディレクトリ内のPNG写真のみを縮小するには:

$ find . -name "*png" -exec convert {} -scale 33% tmp/{} \;
$ ls -m tmp
design_maori.png, waterfall.png

-execで 句、角かっこ {} 見つけたアイテムの代わりになります 処理中です(つまり、一度に1つずつ検索されたPNGで終わるファイル)。 -exec 句はセミコロンで終了する必要がありますが、Bashは通常セミコロンを使用しようとします。バックスラッシュを使用してセミコロンを「エスケープ」します( \; 検索 そのセミコロンをその終了文字として扱うことを知っています。

検索 コマンドはそれが何をするかについて非常に優れており、時にはそれがあまりにも優れている可能性があります。たとえば、それを再利用して別の写真プロセスのPNGファイルを見つけると、いくつかのエラーが発生します。

$ find . -name "*png" -exec convert {} -flip -flop tmp/{} \;    
convert: unable to open image `tmp/./tmp/design_maori.png':
No such file or directory @ error/blob.c/OpenBlob/2643.
...

検索のようです 現在のディレクトリ()にあるものだけでなく、すべてのPNGファイルを見つけました )だけでなく、以前に処理して tmpに配置したものも サブディレクトリ。場合によっては、検索が必要になることがあります 現在のディレクトリとその中の他のすべてのディレクトリ(およびそれらの内のすべてのディレクトリ)を検索します )。これは、特に複雑なファイル構造(音楽ファイルで満たされたアルバムのディレクトリを含む音楽アーティストのディレクトリなど)では強力な再帰処理ツールになりますが、 -maxdepthで制限できます。 オプション。

現在のディレクトリ(サブディレクトリを除く)でPNGファイルのみを検索するには:

$ find . -maxdepth 1 -name "*png"

現在のディレクトリと追加レベルのサブディレクトリでファイルを検索して処理するには、最大深度を1ずつインクリメントします。

$ find . -maxdepth 2 -name "*png"

デフォルトでは、すべてのサブディレクトリに降ります。

楽しみと利益のためにループする

ループを使用すればするほど、時間と労力を節約でき、取り組むことができるタスクも大きくなります。あなたはたった1人のユーザーですが、よく考えられたループを使用すると、コンピューターに大変な作業をさせることができます。

ループは他のコマンドと同じように扱うことができ、またそうすべきです。複数のファイルに対して1つまたは2つのアクションを繰り返す必要がある場合に備えて、ループを手元に置いておきます。ただし、これは本格的なプログラミングへの正当なゲートウェイでもあるため、任意の数のファイルで複雑なタスクを実行する必要がある場合は、ワークフローを計画するために1日のうち少し時間を取ってください。 1つのファイルで目標を達成できる場合は、その繰り返し可能なプロセスを forでラップします。 ループは比較的単純であり、必要な唯一の「プログラミング」は、変数がどのように機能するかを理解し、未処理のファイルと処理済みのファイルを分離するのに十分な編成です。少し練習すれば、Linuxユーザーからループの書き方を知っているLinuxユーザーに移行できるので、そこに出て、コンピューターを機能させることができます。


Linux
  1. Bash履歴コマンドの使用方法

  2. Bashスクリプトをデバッグする方法は?

  3. バッシュを検出する方法>=4.0?

  1. ターミナルでループバッシュスクリプトを停止する方法は?

  2. 変数を使用してBashを使用して複数行の文字列を記述する方法は?

  3. Bashを使用して整数をバイナリファイルに書き込む方法は?

  1. Bashでコメントする方法

  2. 例を使用してBashスクリプトを作成する方法

  3. bashでループの終了ステータスを取得する方法