1. 概要

このチュートリアルでは、Linuxのfindコマンドの-exec引数を見ていきます。 この議論はfindの機能を拡張し、それが知られているスイスアーミーナイフになります。

-exec を使用してコマンドとシェル関数を実行する方法と、それらを制御して実行の効率を向上させる方法について説明します。

2. -execアクション

find コマンドには、式とアクションの2つの主要な部分があります。

最初にfindを使用するときは、通常、式の部分から始めます。 これは、選択するファイルを定義するフィルターを指定できるようにする部分です。

典型的な例は次のとおりです。

$ find Music/ -name *.mp3
Music/Gustav Mahler/01 - Das Trinklied vom Jammer der Erde.mp3
Music/Gustav Mahler/02 - Der Einsame im Herbst.mp3
Music/Gustav Mahler/03 - Von der Jugend.mp3
Music/Gustav Mahler/04 - Von der Schönheit.mp3
Music/Gustav Mahler/05 - Der Trunkene im Frühling.mp3
Music/Gustav Mahler/06 - Der Abschied.mp3

このコマンドを実行すると、Musicディレクトリとそのすべてのサブディレクトリにあるmp3ファイルのリストが表示されます。

この例のアクション部分は、デフォルトのアクション-printです。 このアクションは、結果のパスを改行文字で挟んで印刷します。 他のアクションが指定されていない場合に実行されます。

対照的に、 -exec アクションを使用すると、結果のパスでコマンドを実行できます。

ファイルタイプを決定するために見つけたmp3ファイルのリストでfileコマンドを実行したいとします。これは、次のコマンドを実行することで実現できます。

$ find Music/ -name *.mp3 -exec file {} \;
Music/Gustav Mahler/01 - Das Trinklied vom Jammer der Erde.mp3:
  Audio file with ID3 version 2.4.0, contains:MPEG ADTS, layer III, v1, 128 kbps, 44.1 kHz, Stereo
Music/Gustav Mahler/02 - Der Einsame im Herbst.mp3:
  Audio file with ID3 version 2.4.0, contains:MPEG ADTS, layer III, v1, 128 kbps, 44.1 kHz, Stereo
Music/Gustav Mahler/03 - Von der Jugend.mp3:
  Audio file with ID3 version 2.4.0, contains:MPEG ADTS, layer III, v1, 128 kbps, 44.1 kHz, Stereo
Music/Gustav Mahler/04 - Von der Schönheit.mp3:
  Audio file with ID3 version 2.4.0, contains:MPEG ADTS, layer III, v1, 128 kbps, 44.1 kHz, Stereo
Music/Gustav Mahler/05 - Der Trunkene im Frühling.mp3:
  Audio file with ID3 version 2.4.0, contains:MPEG ADTS, layer III, v1, 128 kbps, 44.1 kHz, Stereo
Music/Gustav Mahler/06 - Der Abschied.mp3:
  Audio file with ID3 version 2.4.0, contains:MPEG ADTS, layer III, v1, 128 kbps, 44.1 kHz, Stereo

-execフラグに渡された引数を分析してみましょう。これには次のものが含まれます。

  1. コマンド:ファイル
  2. プレースホルダー: {}
  3. コマンド区切り文字: \;

これらの3つの部分のそれぞれについて詳しく説明します。

3. コマンド

ここでは、シェルで実行できるすべてのコマンドを使用できます。

これはコマンドを実行するシェルではなく、Linuxのexecを直接使用してコマンドを実行していることに注意してください。これは、シェル拡張がないため、ここでは機能しないことを意味します。シェル。 もう1つの影響は、シェル関数またはエイリアスが使用できないことです。

不足しているシェル関数の回避策として、それらをエクスポートし、ファイルで要求された関数を使用して bash-cを呼び出すことができます。

例は順調です。 マーラーのmp3ファイルのディレクトリを続けます。

トラック名と品質に関する詳細を表示するシェル関数を作成してみましょう。

function mp3info() {
    TRACK_NAME=$(basename "$1")
    FILE_DATA=$(file "$1" | awk -F, '{$1=$2=$3=$4=""; print $0 }')
    echo "${TRACK_NAME%.mp3} : $FILE_DATA"
}

すべてのファイルでmp3infoコマンドを実行しようとすると、-execmp3infoについて知らないと文句を言います。

find . -name "*.mp3" -exec mp3info {} \;
find: ‘mp3info’: No such file or directory

前述のように、これを修正するには、シェル関数をエクスポートして、生成されたシェルの一部として実行する必要があります。

$ export -f mp3info
$ find . -name "*.mp3" -exec bash -c "mp3info \"{}\"" \;
01 - Das Trinklied vom Jammer der Erde :      128 kbps  44.1 kHz  Stereo
02 - Der Einsame im Herbst :      128 kbps  44.1 kHz  Stereo
03 - Von der Jugend :      128 kbps  44.1 kHz  Stereo
04 - Von der Schönheit :      128 kbps  44.1 kHz  Stereo
05 - Der Trunkene im Frühling :      128 kbps  44.1 kHz  Stereo
06 - Der Abschied :      128 kbps  44.1 kHz  Stereo

一部のファイル名にはスペースが含まれているため、結果のプレースホルダーを引用する必要があることに注意してください。

4. 結果プレースホルダー

結果のプレースホルダーは、2つの中括弧{}で示されます。

必要に応じて、プレースホルダーを複数回使用できます。

find . -name "*.mp3" -exec bash -c "basename \"{}\" && file \"{}\" | awk -F: '{\$1=\"\"; print \$0 }'" \;
01 - Das Trinklied vom Jammer der Erde.mp3
  Audio file with ID3 version 2.4.0, contains MPEG ADTS, layer III, v1, 128 kbps, 44.1 kHz, Stereo
02 - Der Einsame im Herbst.mp3
  Audio file with ID3 version 2.4.0, contains MPEG ADTS, layer III, v1, 128 kbps, 44.1 kHz, Stereo
03 - Von der Jugend.mp3
  Audio file with ID3 version 2.4.0, contains MPEG ADTS, layer III, v1, 128 kbps, 44.1 kHz, Stereo
04 - Von der Schönheit.mp3
  Audio file with ID3 version 2.4.0, contains MPEG ADTS, layer III, v1, 128 kbps, 44.1 kHz, Stereo
05 - Der Trunkene im Frühling.mp3
  Audio file with ID3 version 2.4.0, contains MPEG ADTS, layer III, v1, 128 kbps, 44.1 kHz, Stereo
06 - Der Abschied.mp3
  Audio file with ID3 version 2.4.0, contains MPEG ADTS, layer III, v1, 128 kbps, 44.1 kHz, Stereo

上記の例では、basenameコマンドとfileコマンドの両方を実行します。 この場合、コマンドを連結できるようにするために、上記で説明したように別のシェルを生成します。

5. 区切り文字

find コマンドに区切り文字を指定して、-exec引数がどこで停止するかがわかるようにする必要があります。

-exec 引数には、セミコロン(;)またはプラス記号(+)の2種類の区切り文字を指定できます。

シェルでセミコロンを解釈したくないので、エスケープする必要があります(\;)。

区切り文字は、findが式の結果を処理する方法を決定します。 セミコロン(;)を使用すると、-execコマンドが結果ごとに個別に繰り返されます。 一方、プラス記号(+)を使用すると、すべての式の結果が連結され、1回だけ実行される-execコマンドに全体として渡されます。

別の例でプラス記号の使用法を示しましょう。

$ find . -name "*.mp3" -exec echo {} +
./Gustav Mahler/01 - Das Trinklied vom Jammer der Erde.mp3 ./Gustav Mahler/02 -
  Der Einsame im Herbst.mp3 ./Gustav Mahler/03 - Von der Jugend.mp3 ./Gustav Mahler/04 -
  Von der Schönheit.mp3 ./Gustav Mahler/05 - Der Trunkene im Frühling.mp3
  ./Gustav Mahler/06 - Der Abschied.mp3

echo を実行すると、エコー呼び出しごとに改行が生成されますが、プラス区切り文字を使用したため、エコー呼び出しは1回だけ行われました。 この結果をセミコロンバージョンと比較してみましょう。

$ find . -name "*.mp3" -exec echo {} \;
./Gustav Mahler/01 - Das Trinklied vom Jammer der Erde.mp3
./Gustav Mahler/02 - Der Einsame im Herbst.mp3
./Gustav Mahler/03 - Von der Jugend.mp3
./Gustav Mahler/04 - Von der Schönheit.mp3
./Gustav Mahler/05 - Der Trunkene im Frühling.mp3
./Gustav Mahler/06 - Der Abschied.mp3

パフォーマンスの観点から、通常はプラス記号の区切り文字を使用することをお勧めします。ファイルごとに個別のプロセスを実行すると、RAMと処理時間の両方で重大なペナルティが発生する可能性があるためです。

次のいずれかの場合にセミコロン区切り文字を使用することをお勧めします。

  • -exec によって実行されるツールは、引数として複数のファイルを受け入れません
  • 一度に非常に多くのファイルでツールを実行すると、メモリを使いすぎる可能性があります
  • すべての結果を取得するには時間がかかりますが、できるだけ早くいくつかの結果を取得し始めたいと考えています。

6. 結論

結論として、Linuxでfindコマンドを実行するときに-exec引数を使用する方法を示しました。

この引数の個別の部分と、それらを使用してコマンドを効率的に実行する方法について説明しました。