편집하다

편집하다

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대체되는지 \;살펴 보세요 ;. 왼쪽 및 오른쪽 대괄호에도 동일한 문제가 있습니다. 소스에서 세미콜론을 두 번 인용했습니다. 변화

    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"( *현재 디렉터리에 일치하는 파일이 있으면 따옴표가 필요하며, 큰따옴표를 생략해야 하는 이유를 모르는 경우 변수 확장은 큰따옴표로 묶어야 합니다).

답변2

달리기명령 사용법정렬

시도해 봅시다:

find /tmp \( -type f -o -type d \) -ls 

와, 출력이 많이 나오네요...

지금은 괜찮아요:

cmd_list=(find /tmp \()
cmd_list+=(-type f)
cmd_list+=(-o -type d)
cmd_list+=(\) -ls)
"${cmd_list[@]}"

흠...똑같네요!

find /tmp \( -type f -o -type d \) -ls 2>/dev/null | md5sum
eb49dfe4f05a90797e444db119e0d9bd  -
"${cmd_list[@]}" 2>/dev/null| md5sum
eb49dfe4f05a90797e444db119e0d9bd  -

좋아요, 마지막으로:

printf "%q " "${cmd_list[@]}";echo
find /tmp \( -type f -o -type d \) -ls 

하지만

printf "%s " "${cmd_list[@]}";echo
find /tmp ( -type f -o -type d ) -ls

내 전체 실행 버전:

배열을 명령으로 사용하는 예

search() {
    local OPTIND=0 _o _usage _debug=false
    local -a _t _g _cmd=(find)
    read -rN9999 _usage <<-EOUsage
    Usage: $FUNCNAME [-a] [-d] [-i] [-I] [-H] [-l] [-t type [-t type]] \\ 
            /path/ [path2/ ../path3/] pattern
        -t .ext specifying an extension to search for
        -d      debug, will dump command variable before execution
        -[aiIHl] are 'grep' argument, see: man grep.
        many type and many path could be given but only one pattern.
    EOUsage
    while getopts 't:aiIHld' _o ;do
        case $_o in
        d) _debug=true ;;
        t) _t+=(${_t+-o} -name \*.${OPTARG}) ;;
        [aiIHl]) _g+=(-$_o) ;;
        *) echo "${_usage%$'\n'}" ; return 1 ;;
        esac
    done
    _cmd+=(${@:OPTIND:$#-$OPTIND} -type f)
    ((${#_t[@]})) && _cmd+=(\( "${_t[@]}" \))
    _cmd+=(-exec grep ${_g[@]} ${@:$#} {} +)
    $_debug && declare -p _cmd
    "${_cmd[@]}"
}

케어<<-EOUsage부분의 첫 번째 문자EOUsage ~ 해야 하다양식을 만들어보세요! 이 스크립트를 다운로드할 수 있습니다거기또는 다음과 같이 .txt:거기.

노트:일부 grep매개변수는 함수에 제공될 수 있거나 제공되어야 합니다 search:

search -t txt -Il /tmp/path /home/user 'invoice\|bill'

관련 정보