함수 내부에 -f를 설정하세요.

함수 내부에 -f를 설정하세요.

file1.c파일 file2.cfile3.c. 명령 find 출력:

$find -name "*.c"
./file1.c
./file2.c
./file3.c

find 그런 다음 따옴표 없이 사용 하고 싶습니다 .*c.set -f

 $echo $-            # check current options
 himBHs
 $set -f
 $echo $-            # check that f option is set
 fhimBHs
 $find -name *.c
 ./file1.c
 ./file2.c
 ./file3.c
 $set +f             # unset f option

다음 함수에서 동일한 명령을 시도했습니다 .bashrc.

find() {
    set -f
    eval command find $@
    set +f
}

그러나 테스트하면 오류가 발생합니다.

$ . ~/.bashrc && find -name *c
find: paths must precede expression: file1.c
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression

함수에서 이 오류가 발생하는 이유는 무엇입니까? find버전: GNU 4.6.0

답변1

말하지 않았지만 다음과 같이 함수를 호출해야 합니다.

find -name *.c

그러나 와일드카드가 닫히지 않았으므로 *.c호출 전에 셸이 확장됩니다. 따라서 find명령에는 "-name"과 그 뒤에 세 개의 매개변수(오류 메시지)가 표시됩니다.

따옴표 대신 백슬래시를 사용할 수 있습니다.

find -name \*.c

답변2

귀하의 함수는 파일 이름 와일드카드를 비활성화하지만 쉘 확장 와일드카드를 사용하여 호출합니다(파일 이름 와일드카드는아니요호출한 셸에서 닫힙니다.)

즉, 명령의 글로브

find -name *c

find함수를 호출하기 전에 확장하세요. 이로 인해 find유틸리티가 이해하지 못하는 내부 함수 호출이 발생합니다 .

인용된 인수를 사용하여 함수를 호출하면 이 문제를 해결할 수 있습니다.

find -name "*c"

하지만 이제 이 기능은 이미 입력한 명령을 복사할 뿐이므로 전혀 쓸모가 없습니다.

존재하다다음에 추가그것은 쓸모없고 잘못된 것입니다. $@코드에서 인용되지 않았기 때문에 (기본적으로) 공백으로 매개변수를 분할합니다. 이것은 당신을 의미합니다할 수 없다예를 들어 사용하십시오.

find -name "* *"

공백이 포함된 이름을 찾으세요.

또한 어떤 이유로 인해 eval쉘이 $@. 이것은 의미한다

find -name '$(echo hello)'

이름이 있지만 $(echo hello)찾을 수 없는 파일 hello입니다.

또 다른 점은 쉘을 호출하면이미을 사용 set -f하면 해당 기능이 비활성화됩니다.


유용한 함수를 만들어 보겠습니다. 찾아내는 함수수량파일 이름 패턴(예:

myfind "*.c" "*.txt" "* *"

.c위의 명령이 또는로 끝나고 공백을 포함하는 .txt경로 이름을 반환하기를 원합니다 .

기능은 다음과 같습니다.

myfind () {
    # Replace each positional parameter "$pattern"
    # with -o -name "$pattern"
    for pattern do
        set -- "$@" -o -name "$pattern"
        shift
    done
    shift  # shift off the initial "-o"

    find . "$@"
}

위 함수를 호출하면 결국 실행됩니다.

find . -name '*.c' -o -name '*.txt' -o -name '* *'

배열을 목록으로 사용하는 것이 더 편하고 bash조금 더 입력해도 괜찮다면:

myfind () {
    local -a args

    # Build the argument list for find by adding
    # -o -name "$pattern"
    # for each positional parameter 
    for pattern do
        args+=( -o -name "$pattern" )
    done
    args=( "${args[@]:1}" )  # remove the initial "-o"

    find . "${args[@]}"
}

관련 정보