コマンドラインで私にとって非常に効果的なコマンドは次のとおりです。
find . -type f -exec grep -Hin --include=*.h --include=*.c 'somestring' {} \;
上記のコマンドを実行し、検索パスを任意のパスに置き換えると、コマンドはまだ拡張子.
または拡張子を持つファイルのリストのみを表示します。.c
.h
今度は、コマンドを再入力することなく、同様の検索を実行するために少しの変更でスクリプトを実行できるように、変数値と同じコマンドを使用する単純なbashスクリプトを作成したいと思います。しかし、ここで私は脱出規則の悪夢(またはそれに対する適切な理解の欠如)に直面します。
私は次のようにスクリプトを書いた。
#!/bin/bash
path="/home/vinod"
string="somestring"
command="find ${path} -type f -exec grep -Hin --include=*.h --include=*.c '${string}' {} \;"
echo $command
$command
上記のスクリプトを実行すると、次のようにコマンドが1回ではなく2回エコーされます。
find . -type f -exec grep -Hin --include=*.h --include=*.c 'somestring' {} \;
find . -type f -exec grep -Hin --include=*.h --include=*.c 'somestring' {} \;
そして、次のランタイムエラー:
find: missing argument to -exec
エコーが示すように、コマンドはコマンドラインで実行したときとまったく同じで、期待した結果が得られます。
私のスクリプトにどのような問題があるのかというアイデアはありますか?
ティア
ベストアンサー1
コマンドを保存するために変数を使用しないでください。代わりに、変数を使用してデータを保存し、関数を使用してコマンドを保存(定義)します。
検索パスの開始と検索文字列の2つのパラメータを使用してコマンドを生成できます。
開始検索パスも固定されている場合は、検索モードのみを使用するように簡単に変更できます。実際に検索パスが省略された場合は、デフォルト値がユーザー$HOME
ディレクトリになるようにパラメータの順序を逆にしてみましょう。
#!/bin/sh
# Search in *.c and *.h files for a matching pattern
#
pattern=$1
path=${2:-$HOME}
find "${path:-.}" -type f \( -name '*.c' -o -name '*.h' \) -exec grep -Hin -- "$pattern" {} +
ファイルとして保存し、chfind
実行可能にして(chmod a+rx chfind
)に入れます$PATH
。これで他のユーティリティと同じように使用できます。
chfind 'main'
chfind 'main' /some/other/tree/of/files
grep -F
正規文字列ではなく実際に正規表現である検索文字列を使用しないため、このような文を検索することはFILE *fp
機能しません。
最後に、パス名を検索パスに相対的に指定するには、ディレクトリを次に変更してから$path
そこから検索できます。
cd "$path" &&
find -- * -type f \( -name '*.c' -o -name '*.h' \) -exec grep -Hin -- "$pattern" {} +
スクリプトでインラインではなく関数を介してこれを行う方法を説明することをお勧めします。私はあなたの基本要件を解決しました(」コマンドを再入力しなくても、同様の検索を実行するために[...]スクリプトを実行できるように、単純なbashスクリプト[...]を作成したいと思います。"). しかし、関数を使用したい場合はほぼ同じです。
#!/bin/bash
# Search in *.c and *.h files for a matching pattern
#
chFind() {
local pattern=$1 path=$2
find "${path:-.}" -type f \( -name '*.c' -o -name '*.h' \) -exec grep -Hin -- "$pattern" {} +
}
chFind "$1" "${2:-$HOME}"