次のコマンドを実行しようとしています:

find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar "{}" + 

これはエラーを返します:

find: missing argument to -exec 

このコマンドはmanページと一致しているようで、何が問題なのかわかりません。 :

-execコマンド{} +

-execオプションのこのバリアントは、選択したファイルに対して指定されたコマンドを実行しますが、コマンドラインは、選択した各ファイル名を最後に追加することで作成されます。コマンドの呼び出しの総数は、一致するファイルの数よりもはるかに少なくなります。コマンドラインは、xargsが作成するのとほぼ同じ方法で作成されます。コマンドライン。コマンド内で許可される「{}」のインスタンスは1つだけです。コマンドは開始ディレクトリで実行されます。

次のことも試しました:

find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar {} + find a/folder b/folder -name *.c -o -name *.h -exec "grep -I foobar" {} + find a/folder b/folder -name *.c -o -name *.h -exec "grep -I foobar" "{}" + find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar "{}" + find a/folder b/folder \( -name *.c -o -name *.h \) -exec grep -I foobar "{}" + find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar "{}" \+ 

コメント

  • +最後に?find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' \+
  • 古いバージョンのGNU findを使用している可能性があります。 -exec cmd {} +バリアントはPOSIXであり、80年代から利用可能ですが、GNU findはそれを(比較的)最近(2005年)に追加しただけです。 find --versionは何を教えてくれますか?
  • @Koveras、それならそれでしょう。 -exec {} +は2005年の4.2.12で追加されました。古いGNU検索では、(POSIX以外の)-print0 | xargs -r0を使用して何かを取得できます。同様。 4.1は1994年のものです。
  • JRFergusonは(削除された回答で)-nameパターンを指摘しました引数は引用符で囲む必要があります:-name "*.c" -o -name "*.h"。これは真実ですが、-execエラーとは関係ありません。 Gillesだけが言及していますが、他のすべての回答ではワイルドカードが引用符で囲まれていることに気付くでしょう。 …(続き)
  • (続き)…jlliagreの答えは、説明なしで名前の式を-name "*.[ch]"に折りたたんでいます。これには、コマンドラインを簡素化し、具体的には-oを排除するという利点があります。 -oを含む式を見つけるのは難しいです。あなたは間違っています。コマンドがエラーにならないように修正されている場合(Gillesの回答のように)、grep.hでのみ実行されます。ファイル。 '(' -name '*.c' -o -name '*.h' ')'を実行する必要があります。

回答

ありました引用符の代わりに使用されるバッククォート(後の質問の編集で削除)、必要な場所での引用符の欠落、役に立たない余分な引用符、グループ-o句、および使用されるfindのさまざまな実装(詳細については、コメントとチャットを参照してください)。

とにかく、コマンドは次のように簡略化できます。

find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} + 

または、古風なGNU検索バージョンを使用する場合、これは常に機能するはずです:

find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} \; 

コメント

  • おっと、バッククォートではなく引用符であることが意図されていました。
  • 引用符は{}はシェルにとって特別な意味はありません。
  • マニュアルページの検索から:”文字列’ { } ‘は一部のバージョンのfindのように、単独の引数だけでなく、コマンドの引数で発生するすべての場所で処理されている現在のファイル名に置き換えられます。これらの構造は両方とも、シェルによる拡張から保護するために、エスケープするか(’ \ ‘)引用する必要がある場合があります。”
  • マニュアルページで実際に読んだのですが、’認識しているシェルがないのは事実です。中括弧を引用する必要があります。どのシェルを使用していますか?
  • bash。引用符の有無にかかわらず、とにかくエラーが発生します。

回答

-exec」は通常、-execへの引数にターミネーターがないことを意味します。ターミネータは、文字;のみを含む引数である必要があります(シェルコマンドで引用符で囲む必要があるため、通常は\;または";")、または{}+を含む2つの連続する引数。

Stephane Chazelasは、-exec … {} +。 / div>、-exec {} \;のみ。GNUは-exec … {} +を後から採用しましたが、あまり古くないツールスイート( Cygwin aなど)を入手することをお勧めします。 >、これにはgitなどが含まれます。または、 GNUwin32 には、gitがありませんが、bad-employee-trying-to-use-linuxがありません。 -but-we-impose-windows vibe(Cygwinが提供)。この機能は、9年以上前のバージョン4.2.12で追加されました(GNU findを作成するために最後に識別された機能でした。 POSIX準拠)。

古いGNU検索に固執する場合は、-print0xargs -0同様の機能を取得するには:グループ化されたコマンド実行、任意のファイル名をサポートします。

find a/folder b/folder -name "*.c" -o -name "*.h" -print0 | xargs -0 grep -I foobar /dev/null 

常にfindコマンドライン。それ以外の場合、.cファイルを含むディレクトリからこのコマンドを実行すると、引用符で囲まれていない*.c woul d現在のディレクトリにある.cファイルのリストに展開されます。

/dev/null

コマンドラインは、findがたまたま一致するものを1つ見つけた場合でも、grepが常にファイル名を出力するようにするためのトリックです。 GNU findの場合、別の方法はオプション-Hを渡すことです。

コメント

  • 何をしますかcygwinが提供するbad-employee-trying-to-use-linux-but-we-impose-windowsの雰囲気とはどういう意味ですか?
  • GNUwin32は’期待していません:(
  • 質問に対する私のコメントを参照してください。
  • セミの周りの引用は、package.jsonスクリプト内から機能しました。

回答

次のようなコマンドの場合

find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar {} + 

エラーが返される

find: missing argument to -exec 

考えられる原因は古すぎるGNU find構文-exec mycommand {} +。その場合、パフォーマンスの低い置換は-exec mycommand {} \;を実行することです。これにより、複数のターゲットを収集するのではなく、見つかったターゲットごとに1回mycommandが実行されます。 mycommandを1回だけ実行します。

ただし、GNU find doe sサポートされていません。例

find . -type f -and -name "*.ttf" -exec cp {} ~/.fonts + 

GNU findはリテラルの組み合わせ{} +{} additional parameters +の代わりに/ div>。中括弧と+文字の間に何も存在できないことに注意してください。これを試してみると、同じエラーが発生します。

find: missing argument to -exec 

回避策は、構文{} additional parameters \;を使用することです。動作しますが、見つかったターゲットごとに1回コマンドを実行します。 GNU findでより高いパフォーマンスが必要な場合は、指定された引数に追加のパラメーターを追加できるラッパースクリプトを作成する必要があります。

 #!/bin/bash exec mycommand "$@" additional parameters  

のようなもので十分です。または、一時ファイルを作成したくない場合は、ワンライナーを使用して、次のようにパラメーターの順序を変更できます。

find . -type f -and -name "*.ttf" -exec bash -c "mycommand "$@" extra arguments" {} + 

-cフラグの後にbashの特殊文字を二重エスケープする必要がある場合があることに注意してください。

コメント

  • (1)質問に実際に答える上記の部分は、すでに他の人から与えられたものです。 (2)あなたが説明しているのは、GNU findの欠陥や欠陥ではなく、POSIXで指定されている正しい動作です
  • +1最後に、追加のパラメータが機能しない理由に答える人’! POSIX定義の欠陥のようです。
  • ‘ GNU findの場合’おそらくGNU cpを取得しています。この場合、find ... -exec cp --target-directory ~/.fonts {} +を実行ストリングの最後に{}を保持することができます。

回答

find . -type f -perm 0777 -exec chmod 644 {}\;

エラーが発生しましたfind: missing argument to ``-exec"

{}\の間にスペースを追加すると、修正されました:

find . -type f -perm 0777 -print -exec chmod 644 {} \;

コメント

  • find当面の質問のコマンド。
  • 質問では、私が理解したことは問題ありませんが、問題は同じです” find:引数がありません“ -exec ‘ “に、問題はさまざまな原因で発生する可能性があります-2つの理由、同じ問題ステートメントを見たので答えました。
  • @Kusalanandaよろしくお願いします。noobは、OPが質問のタイトルと本文の両方に記載している、報告されたエラーの解決策を提供しました。
  • @bvj findへの-execオプションの+形式を使用します。この回答は、質問をしているユーザーにはない問題を修正しています。

回答

過去のexec構文での頭痛の種。ほとんどの日、私はより良いbash構文を好みます:

for f in `find a/folder b/folder -name "*.[ch]"`; do grep -I foobar $f; done 

ファイルをグループとして扱いたい場合、それぞれが連続して評価されるため、いくつかの制限があります。ただし、出力を他の場所にうまくパイプすることができます

コメント

  • これは機能する傾向がありますが、純粋な検索バージョンよりも大幅に有用性が低くなります。名前に空白が含まれるファイルを正しく処理できません。
  • いいえ、’これを行わないでください。これは、ファイルにスペースやその他の「奇妙な」文字が含まれるとすぐに壊れます。これはfind … -exec … \;よりも複雑で遅いため、ファイル名がわかっていても’これを使用する理由はありません。飼いならされました。
  • これは、ファイル名に基づいて複数行のロジックを実行する必要がある状況(文字の削除、ディレクトリの作成、ファイルの移動など)に役立ちました。 1つのexecで複数のことを実行できるようにすることは、私がこれに費やしたかった5分間の頭痛の種でした。私のファイル名は飼いならされていて、これで私の問題は解決しました:)

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です