find(1)の-execオプションを理解する(中括弧とプラス記号)


17

次のコマンドを使用して、誰かが中括弧({})とプラス記号(+)を終了する目的を正確に説明できますか?

また、コマンドから除外された場合、コマンドはどのように動作しますか?

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

回答:


19

中括弧はfindコマンドの結果に置き換えられ、chmodそれぞれに対して実行されます。+作るには、find可能な限り少数のコマンドとして実行しよう(そう、chmod 775 file1 file2 file3とは対照的にchmod 755 file1chmod 755 file2chmod 755 file3)。それらがなければ、コマンドはエラーを返します。これはすべてで説明されていman findます:

-exec command ;

      コマンドを 実行します。0ステータスが返された場合はtrue。に続くすべての引数findは、 ' ;'で構成される引数が検出されるまで、コマンドの引数と見なされます。文字列「{}」は、一部のバージョンのように、単独の引数だけでなく、コマンドの引数で発生するすべての場所で処理される現在のファイル名に置き換えられますfind。…

-exec command {} +

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


12

テルドンの答えに加えて、

  • 「明らかに」-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’エラーメッセージが表示されます。

    • cpmvコマンドに固有のこれの回避策は

      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 {} +

    他のすべての名前をパラメーターとして使用して、スクリプトの1つを実行します。これは言うことに似ています

    ./*.sh
    

    シェルコマンドとして、find結果をソートすることを保証しないことを除いて、あなたが実行しているようにaaa.sh (アルファベット順で最初の*.shファイル)実行することは保証されません./*.sh

  • その一面はfind、初心者には完全に明らかではないかもしれませんが、コマンドラインは、事実上、難解な言語の実行可能なステートメントです。例えば、

    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
    

    一部の-キーワードは、実行可能なアクションとテストの両方です。特に、これはtrueに当てはまり-exec … ;ます。例えば、

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

    に変換する

    各ファイルについて
        プレーンファイル(ディレクトリではない)の場合
        それから
            grep -q cat filenameを実行します
            プロセスが成功した場合(つまり、ステータス0で終了した場合)
            それから
                ファイルの名前を出力します
            終了する
        終了する
    終了ループ

    文字列「cat」を含むすべてのファイルの名前を出力します。そして、これはgrepそれ自体で(-l小文字のLオプションを使用して)find行うことができますが、特定の文字列を含み、特定のサイズを持ち、特定の所有者が所有しているファイルを見つけるために使用すると便利ですそして、特定の時間範囲で変更されました…。

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

  • 上記の裏返しは、find無効な引数を指定するか、読み取ることができないディレクトリに遭遇しない限り、通常、終了ステータス0で終了します。あなたが実行することをプログラムが(ゼロ以外の終了ステータスを持って終了し)失敗した場合であっても、 find0の終了ステータスで終了します  除き、  あなたが実行することをプログラムがあれば-exec … +(ゼロ以外の終了ステータスで終了)を失敗し、 find終了しますゼロ以外の終了ステータス。

数百のバージョンのfind(1) テストとfindいくつかのシステムで実際に行うことのテストに加えて、 The Open Group Base Specifications Issue 7、2013 Edition は、何をするfind必要があるか、何をするか、してはいけないかに関する情報の一部を提供しました。


3
使用する例... -exec mv {} {}.bak ...は、すべてのfind実装で期待どおりに動作することを保証されていないことに注意してください。POSIX標準状態{}は、常に認識されるために単独で表示されなければなりません。前者の場合、コマンド全体が本質的に最後に見つかったファイルを除くすべてのファイルを削除します
...-jlliagre
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.