次のコマンドを実行しようとしています。
find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' +
エラーが返されます。
find: missing argument to -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 '{}' \+
答え1
引用符の代わりにバックティックを使用します(質問の後続の編集から削除されます)、必要に応じて引用符の欠落、無用な追加の引用符、グループ化句の括弧の欠落、および使用されている-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 {} \;
答え2
「引数の欠落」とは、通常、引数に終端が欠けていることを-exec
意味exec
します。ターミネータは文字専用引数;
(シェルコマンドで引用する必要があるため、通常は\;
orで書かれている';'
)またはsumを含む2つの連続し{}
た引数でなければなりません+
。
ステファン・チャゼラス確定findをサポートしていない以前のバージョンのGNU findを使用しています。 GNUはfindを遅く採用しましたが、それほど古いツールバー(例-exec … {} +
:-exec {} \;
-exec … {} +
シビン、gitなどを含むGNUwin32、gitが不足していますが、Cygwinが提供する悪いウィンドウを課す雰囲気はありません)。この機能は、9年前のバージョン4.2.12(find
GNU POSIX互換のために最後に確認された機能)に追加されました。
以前のGNUクエリを引き続き使用するには、-print0
withを使用xargs -0
して同様の機能(グループ化されたコマンドの実行、任意のファイル名のサポート)を取得できます。
find a/folder b/folder -name '*.c' -o -name '*.h' -print0 | xargs -0 grep -I foobar /dev/null
コマンドラインでは常にワイルドカード文字を引用してくださいfind
。それ以外のファイルが含まれているディレクトリでこのコマンドを実行すると、引用符で囲まれていない内容は現在のディレクトリのファイルのリスト.c
に展開されます。*.c
.c
単一の一致を見つけても、grepが常にファイル名を印刷できるようにするトリックがコマンドライン/dev/null
に追加されました。 GNU findのもう一つのアプローチはoptionsを渡すことです。grep
find
-H
答え3
次のようなコマンドがあれば
find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar {} +
戻りエラー
find: missing argument to -exec
考えられる理由は、GNUが古すぎて構文をサポートしていfind
ないためです-exec mycommand {} +
。この場合、パフォーマンスが低い代替手段は、複数のターゲットを収集して1回だけ実行するのではなく、見つかった各ターゲットに対して1回実行すること-exec mycommand {} \;
です。mycommand
mycommand
ただし、GNUはfind
以下をサポートしていません。
find . -type f -and -name "*.ttf" -exec cp {} ~/.fonts +
find
GNUは文字通りの組み合わせのみをサポートし{} +
、一般的な組み合わせはサポートしないからです{} additional parameters +
。中かっこと文字の間には何も入力できません+
。これを試みると同じエラーが発生します。
find: missing argument to -exec
{} additional parameters \;
回避策は機能しますが、見つかった各ターゲットに対してコマンドを一度実行する構文を使用することです。より高いパフォーマンスのGNUが必要な場合は、find
指定されたパラメータに追加のパラメータを追加するラッパースクリプトを作成する必要があります。それはまるで
#!/bin/bash
exec mycommand "$@" additional parameters
十分に良いでしょう。あるいは、一時ファイルを生成したくない場合は、次の1行コマンドを使用してパラメータの順序を変更できます。
find . -type f -and -name "*.ttf" -exec bash -c 'mycommand "$@" extra arguments' {} +
これを行うだけですmycommand {list of ttf files} extra arguments
。フラグの後にbashの特殊文字を2回エスケープする必要があるかもしれません-c
。
答え4
私は過去にexec構文のために頭痛を経験しました。今、ほとんどの場合、より良いbash構文を好みます。
for f in `find a/folder b/folder -name "*.[ch]"`; do grep -I foobar $f; done
各ファイルは順次評価されるため、ファイルをグループとして扱う場合はいくつかの制限がありますが、出力を別の場所にパイプすることができます。