編集する

編集する

bashでエラーなしで次のコマンドを実行できます。

$ find /d/Code/Web/Development/Source/ \( -name '*.cs' -o -name '*.cshtml' \) -exec grep -IH UserProfileModel {} \;

このコマンドをすばやく実行するために、.bash_aliasesに関数を作成しました。

search() {
    local file_type file_types find_cmd opt OPTARG OPTIND or pattern usage
    
    usage="Usage: search [OPTION] ... PATTERN [FILE] ...
Search for PATTERN in each FILE.
Example: search -t c -t h 'hello world' /code/internal/dev/ /code/public/dev/

Output control:
  -t    limit results to files of type"
    
    if [[ $1 == --help ]]; then
        echo "$usage"
        return
    fi
    
    file_types=()
    while getopts ":t:" opt; do
        case $opt in
            t)
                file_types+=("$OPTARG")
                ;;
            ?)
                echo "$usage"
                return
                ;;
        esac
    done
    shift $((OPTIND-1))
    
    if (( $# == 0 )); then
        echo "$usage"
        return
    fi
    
    pattern=$1
    shift
    
    if (( $# == 0 )); then
        echo "$usage"
        return
    fi
    
    find_cmd=(find "$@" '\(')
    or=""
    for file_type in "${file_types[@]}"; do
        find_cmd+=($or -name \'*.$file_type\')
        or="-o"
    done
    find_cmd+=('\)' -exec grep -IH "$pattern" {} '\;')
    
    "${find_cmd[@]}"
}

ただし、関数でエラーが発生します。

find: paths must precede expression

最後の行をに変更すると、上記とecho "${find_cmd[@]}"同じコマンドが印刷されます。

$ search -t cs -t cshtml UserProfileModel /d/Code/Web/Development/Source/
find /d/Code/Web/Development/Source/ \( -name '*.cs' -o -name '*.cshtml' \) -exec grep -IH UserProfileModel {} \;

コンソールで実行すると機能しますが、関数内で実行すると失敗する理由を理解できません。

また、関数をコマンドで減らすと機能します。

search() {
    find /d/Code/Web/Development/Source/ \( -name '*.cs' -o -name '*.cshtml' \) -exec grep -IH UserProfileModel {} \;
}

Notepad ++で.bash_aliasesを編集していますが、行末がUnix形式であることを確認しました。

編集する

以下のF. Hauriの提案に従ってデバッグを有効にしました。明らかに、これは実行された実際のコマンドです。

find /d/Code/Web/Development/Source/ '\(' -name ''\''*.cs'\''' -o -name ''\''*.cshtml'\''' '\)' -exec grep -IH UserProfileModel '{}' '\;'

この情報をどのように解釈するのかわかりません。角かっこの前にエスケープ文字を削除すると、他のエラーが発生します。

find: missing argument to -exec

ベストアンサー1

ヒント:set -xトラッキングモードを有効にするには実行してください。 Bash は各コマンドを実行する前に印刷します。set +xトレースモードをオフにするには実行してください。

+ find . '\(' '\)' -exec grep -IH needle '{}' '\;'

最後のパラメータがどのようにfind置き換えられるか\;を見てください;。左右の角かっこにも同じ問題があります。ソースからセミコロンを2回引用しました。変化

    find_cmd=(find "$@" '\(')
    find_cmd+=('\)' -exec grep -IH "$pattern" {} '\;')

到着

    find_cmd=(find "$@" '(')
    find_cmd+=(')' -exec grep -IH "$pattern" {} ';')

または

    find_cmd=(find "$@" \()
    find_cmd+=(\) -exec grep -IH "$pattern" {} \;)

また、-name \'*.$file_type\'無効な引用符があります。名前が一重引用符で始まり、終わるファイルを探しています。これを実行します-name "*.$file_type"*現在のディレクトリに一致するファイルがある場合は引用符が必要です。二重引用符を省略する理由がわからない場合は、変数拡張子を二重引用符で囲む必要があります)。

おすすめ記事