本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。今回は、同じ処理を繰り返し実行する「for」コマンドです。
本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。今回は同じ処理を繰り返し実行する「for」コマンドです。
「for」は、何かの条件を指定して、繰り返し処理を行う際に使うbashの内部コマンドです。「1から10まで」のように具体的に数を指定して繰り返す他、ファイル全体の数が分からなくても、指定したファイル1つ1つに対して処理を実行したいときに使います。
forコマンドは主にシェルスクリプトで使用します。しかし、コマンドラインで複数ファイルに対して同じ処理を施すときにも役立ちます。
for 変数 in リスト; do コマンド; done
for ((式1; 式2; 式3)); do コマンド; done
※do以下のコマンドを複数書く場合は「;」で区切る。「;」の位置で改行できる。
※「((式1; 式2; 式3))」の使い方については、連載第218回を参照。
forコマンドにはオプションはありません。
書式 | 意味 |
---|---|
${変数:-文字列} | 変数が未設定または空の場合、指定した文字列を使用する |
${変数:=文字列} | 変数が未設定または空の場合、指定した文字列を変数にセットする |
${変数:?文字列} | 変数が未設定または空の場合、エラーとし、指定した文字列を出力する |
${変数:+文字列} | 変数が未設定または空ではない場合、指定した文字列を変数にセットする |
${変数:位置:長さ} | 指定した位置から、指定した長さ(最大長)分を取り出す(※1) |
${変数:位置} | 指定した位置以降全てを取り出す(※1) |
${変数::長さ} | 先頭から指定した長さ分を取り出す |
${変数::-長さ} | 末尾から指定した長さ分を取り出す |
${!接頭辞*} | 先頭部分が一致する変数名を取得 |
${!接頭辞@} | 先頭部分が一致する変数名を取得 |
${#変数} | 変数の長さ |
${変数#パターン} | パターンに前方一致した部分を取り除く(最短一致、※2) |
${変数##パターン} | パターンに前方一致した部分を取り除く(最長一致、※2) |
${変数%パターン} | パターンに後方一致した部分を取り除く(最短一致) |
${変数%%パターン} | パターンに後方一致した部分を取り除く(最長一致) |
${変数/パターン/文字列} | 指定したパターンを文字列で置き換える |
${変数^パターン} | パターンにマッチした最初の文字を、小文字から大文字に変換する |
${変数^^パターン} | パターンにマッチした文字全てを、小文字から大文字に変換する |
${変数,パターン} | パターンにマッチした最初の文字を、大文字から小文字に変換する |
${変数,,パターン} | パターンにマッチした文字全てを、大文字から小文字に変換する |
※1 マイナスの位置を指定した場合は末尾から数える。
※2 tempという変数の内容が「/usr/bin/man」の場合、${temp#*/}は「usr/bin/man」、${temp##*/}は「man」となる。
コマンドの実行結果を使って繰り返し処理を実行するには、「for 変数 in `コマンド`」、またはbashのパラメーター展開を用いた「for 変数 in $(コマンド)」を使います(画面1)。
forコマンドの基礎編(連載第215回)では、「for f in *.txt 〜」を使って、カレントディレクトリの「*.txt」を対象に処理を行いました。これをコマンドの実行結果と組み合わせて、「for f in `ls *.txt`」と書くことができます。
for f in *.txt; do echo $f; done
(「*.txt」に当てはまる名前のファイルそれぞれに対しechoコマンドを実行)
for f in `ls *.txt`; do echo $f; done
(「ls *.txt」の実行結果に1つ1つに対しechoコマンドを実行)
画面2は、「カレントディレクトリ下で1週間以内に更新したファイル」をfindコマンド(第32回)で探し、それに対し「ls -l」コマンドを実行しています(※3)。
findコマンドのオプションが少々長いため、画面2では、コマンドラインで「for f in `コマンド`」「do 実行結果に対して行いたい処理」「done」という3行に分けて入力しています(第215回から「コマンドラインで改行する」)。
※3 ここではforコマンドを試すために、findコマンドの結果を使ってlsコマンドを別途実行している。より効率良くfindコマンドの実行結果を「ls -l」のように出力するには、findコマンドの「-exec」アクションを使用するか、あるいは、「-printf」や「-ls」を使う。
画面2のような使い方をする場合、まずfindコマンドだけを実行して、実行結果を確認してからfor文を実行することが多いでしょう。
その場合、ヒストリ機能を使って「for f in `!!` 〜」のように入力することで、「for f in `直前に実行したコマンド`」という指定ができます(画面3)。入力の手間が減ります。
処理したい対象のリストが書かれたファイルを読み、順次処理するには、catコマンドと組み合わせます。
例えば、画面4では、リストファイルを読み込んで、1つずつechoコマンドを実行しています。ファイル名の先頭と最後に「等号」を追加できました。
「for in 〜 」を実行する際、区切り文字が問題になることがあります。デフォルトでは空白文字、つまり、スペースやタブ、改行文字などを区切り文字として扱います。
区切り文字を変更するには、シェル変数IFSを使います。画面5では、デフォルトの状態と、IFSに改行を設定した場合を比較しました(※4)。
※4 画面5では最後に「unset IFS」を実行し、区切り文字の設定を変更前に戻している。なお、シェルスクリプト中で区切り文字を変更する場合は、bashが別途起動しているため、unset IFSを実行する必要はない。
for f in `cat ファイル名`; do echo =$f=; done
(ファイル名が書かれたファイルに従って、echoコマンドを実行する)
西村 めぐみ(にしむら めぐみ)
PC-9801NからのDOSユーザー。PC-486DX時代にDOS版UNIX-like toolsを経てLinuxへ。1992年より生産管理のパッケージソフトウェアの開発およびサポート業務を担当。著書に『図解でわかるLinux』『らぶらぶLinuxシリーズ』『Accessではじめるデータベース超入門[改訂2版]』『macOSコマンド入門』など。2011年より、地方自治体の在宅就業支援事業にてPC基礎およびMicrosoft Office関連の教材作成およびeラーニング指導を担当。
Copyright © ITmedia, Inc. All Rights Reserved.