find(1) の -exec オプションについて (中括弧とプラス記号)

find(1) の -exec オプションについて (中括弧とプラス記号)

次のコマンドを使用して、閉じ括弧({})とプラス記号(+)の正確な目的を説明できますか?

注文から除外した場合、注文操作はどのように異なりますか?

find . -type d -exec chmod 775 {} +

答え1

中括弧はコマンドの結果に置き換えられ、findすべてのchmodコマンドで実行されます。できるだけ少ない数のコマンドを実行しようとします+(したがって、、の逆)。それらがなければ、コマンドはエラーを発生させます。すべてそこにいるfindchmod 775 file1 file2 file3chmod 755 file1chmod 755 file2chmod 755 file3man find:

-exec command ;

      実装する注文する;戻り状態が0の場合は真です。以下のすべてのパラメータfind;''で構成された引数が見つかるまで、コマンドの引数として扱われます。文字列 ' {}' は、一部のバージョンと同様に、個々の引数だけでなく、コマンド引数に現れるすべての場所で処理される現在のファイル名に置き換えられます.find。 …

-exec command {} +

      この-execアクションのバリエーションは、選択したファイルに対して指定されたコマンドを実行しますが、コマンドラインは選択した各ファイル名を最後に追加することによって構成されます。コマンドの総呼び出し数は、一致するファイルの数よりはるかに少なくなります。 …

答え2

Teddenの回答に加えて

  • 「Obviously」はセミコロン()またはプラス記号()で終わる必要があります-exec …。セミコロンはシェル(または少なくとも私が使用したすべてのシェル)の特殊文字なので、使用したい場合;+findコマンドの一部として、エスケープまたは引用する必要があります(\;、、、";"または';')。
  • を使用すると、-exec … ;この{}文字列はコマンドに複数回表示されることがあります。0を含む、または2つ以上の場所に関係なく。  バラよりこれ-execを使用したくない理由については、たとえば、2つ以上の形状を持つことが便利です{}   (少なくとも)一部のバージョンでは単語自体が必要ないからfindです{}。または終わりです。

    find . -type f -exec mv {} {}.bak ";"
    

    -exec … +{}文字列として〜しなければならない前の最後のパラメータとして表示されます+。このようなコマンド

    find . -name "*.bak" -exec mv {} backup_folder +
    

    その結果、不明なfind: missing argument to ‘-exec’エラーメッセージが表示されます。

    • cpコマンドに関連するmv回避策は次のとおりです。

      find . -name "*.bak" -exec mv -t backup_folder {} +
      

      または

      find . -name "*.bak" -exec mv --target-directory=backup_folder {} +
      

    単語{}自体は単語でなければならず、先頭または末尾に他の文字を使用することはできません。そして(少なくとも)いくつかのバージョンではfind{}

  • 知的注意:次のように言うことができます。

    探す。 -name "*.sh" -type f -executable -exec {}これにはオプションのパラメータがあります。";"

    各スクリプトを実行します。しかし、

    探す。 -name "*.sh" -type f -executable -exec {}+

    走る一つスクリプトの名前と他のすべてのスクリプトの名前を引数として使用します。これと似ています。

    ./*.sh
    

    シェルコマンドとしてfind結果の順序を保証しないので、次のように実行できるという保証はありませんaaa.sh (アルファベット順の最初のファイル)。*.sh./*.sh

  • find初心者には明確ではないかもしれない1つの側面は、コマンドラインが実際には実行文神秘的な言語で。例えば、

    find . -name "*.sh" -type f -executable -print
    

    方法

    for each file
        if the file’s name matches `*.sh` (i.e., if it ends with `.sh`)
        then
            if it is a plain file (i.e., not a directory)
            then
                if it is executable (i.e., the appropriate `---x--x--x` bit is set)
                then
                    print the file’s name
                end if
            end if
        end if
    end loop
    

    または簡単に言えば、

    for each file
        if the file’s name matches `*.sh`  AND  it is a plain file  AND  it is executable
        then
            print the file’s name
        end if
    end loop
    

    一部の-キーワードは実行可能なジョブでありテストです。特に、-exec … ;例えば、

    find . -type f -exec grep -q cat {} ";" -print
    

    次のように翻訳

    各ファイルに
        通常のファイルの場合(ディレクトリ以外の場合)
        それから
            grep -q catの実行ファイル名
            プロセスが成功した場合(つまり、状態0で終了)
            それから
                ファイル名の印刷
            もしかして
        もしかして
    エンドループ

    これにより、文字列 ""を含むすべてのファイルの名前が印刷されますcat。そしてこれは(小文字)オプションをgrep使って自分で行うことができますが、-l特定の文字列を含み、特定のサイズを持ち、特定の所有者が所有するファイルを見つけることと組み合わせるとL便利です。所有者findであり、特定の時間範囲内で修正が行われました。

    ただし、これは機能しません-exec … +-exec … +1つのコマンドが複数のファイルで実行されるため、for each file …ループ内で論理条件として使用することは意味がありません。

  • 上記の状況の反対側は、find誤った引数を提供または読み取れないディレクトリに遭遇しない限り、通常は終了状態0で終了することです。実行したプログラムが失敗しても(ゼロ以外の終了状態で終了)、終了 find状態0で終了します。  とは別に 実行しているプログラムが-exec … +失敗すると(ゼロ以外の終了状態で終了)、ゼロ以外の終了 find状態で終了します。

find(1) 百万のバージョンを実行し、findいくつかのシステムで実際に機能する機能をテストすることに加えてOpen Group 基本仕様 2013年7号版find何をすべきか、できること、やらないことについての情報を提供します。

関連情報