条件に合うファイルに対してコマンドを実行する方法
例えば、「現在のディレクトリ内にある PNG フォーマットの画像ファイルのファイルサイズを optipng コマンドで最適化したい」という要望があったとします。
PNG ファイルのファイルサイズの最適化については「OptiPNG で PNG ファイルの最適化を行う方法」をみてください。
ディレクトリ内には、PNG ファイルの他、JPEG ファイルなど混在しているので、ファイルの拡張子でフィルターをかけてファイルを探して、見つかったファイル名を optipng に渡すことになります。
こうした場合は、find コマンドを使うと便利です。
次のコマンドでは、拡張子でファイルを探し、見つかったファイル名を optipng コマンドに渡しています。
$ find . -type f -iname '*.png' -exec optipng -o5 {} \;
パラメータの説明をします。
最初のドット . は現在のディレクトリを表しています。ファイル検索の開始点になります。
-type f オプションで、ファイルのタイプとして f を指定することで、ディレクトリなどではなく「通常のファイル」を指定しています。
-iname '*.png' オプションで、ファイル名による検索を行っています。 -iname オプションは大文字小文字によらないファイル名の検索です。一方、-name とすると大文字小文字を区別します。
-exec optipng -o5 {} \; によって、見つかったファイルに対して実行するコマンドを指定しています。
-o5 は optipng コマンドのオプションです。最適化のレベルを指定しています。
{} の箇所は検索で見つかったファイル名で置き換えられます。
\; と + の違い
\; はコマンドの終わりを示しています。その他、+ で終わることもできます。
この違いは何でしょうか。
+ ではこの場合は {} のところが単一のファイル名ではなく、ファイルのリストを受けとります。
例えば、今、ファイルが三つ (file1, file2, File3) があり、それぞれに対して echo コマンドを実行してみましょう。
$ ls file1 file2 File3 subdir $ find . -type f -iname 'file*' -exec echo '---' {} \; --- ./file1 --- ./File3 --- ./file2 $ find . -type f -iname 'file*' -exec echo '---' {} + --- ./file1 ./File3 ./file2
\; で終わった場合はファイル名三つに対して、echo コマンドがそれぞれ 1 回ずつ実行されています。
しかし、+ の場合は、echo コマンドは一度だけ実行されています。
cat コマンドでファイルの内容を連結する時のように、 複数のファイル名を渡したい場合は + を使うと良いです。
上述の optipng の場合は、複数のファイル名を受け取れるので + をつけても構いません。 しかし、optipng の処理自体ファイルひとつひとつ行われるものなので、\; でも + でもどちらでも構いません。
ここでは find コマンドを使いましたが、find コマンドを使うと、ファイルの検索を様々な方法で行うことができます。 検索の方法について他の記事をみてください。