Bash 기능에서 따옴표를 올바르게 사용하는 방법은 무엇입니까?

Bash 기능에서 따옴표를 올바르게 사용하는 방법은 무엇입니까?

.bashrc내 파일 에 다음 bash 함수를 정의하려고 합니다 .

function myfind() {
    find $1 -not -path venv -not -path .tox -name "$2" | xargs grep -n "$3"
}

이것은 내 기대에 미치지 못했습니다. 이 기능을 사용하여 파일에서 텍스트를 검색할 때, 예를 들어

myfind . *.py test

아무것도 반환하지 않습니다. 하지만 표현을 직접 사용할 때 즉

find . -not -path venv -not -path .tox -name "*.py" | xargs grep -n "test"

일부 일치 항목을 반환합니다.

나는 다음과 같은 큰 따옴표를 사용해 보았습니다.

function myfind() {
    find $1 -not -path venv -not -path .tox -name '"$2"' | xargs grep -n '"$3"'
}

또는

function myfind() {
    find $1 -not -path venv -not -path .tox -name "'$2'" | xargs grep -n "'$3'"
}

이런 따옴표를 피하려고 노력하십시오

function myfind() {
    find $1 -not -path venv -not -path .tox -name \"$2\" | xargs grep -n \"$3\"
}

그러나 이들 중 어느 것도 작동하지 않는 것 같습니다.

이 bash 함수가 매개변수 주위에 따옴표를 "사용"하도록 수정하려면 어떻게 해야 합니까?

답변1

티팀:

myfind() {
  find "$1" '(' -name venv -o -name .tox ')' -prune -o \
            -name "$2" -type f -exec grep -Hne "$3" -- {} +
}

그런 다음:

myfind . '*.py' test

당신은 또한 볼 수 있습니다찾기 결과를 반복하는 것이 왜 나쁜 습관입니까?그러한 출력을 호출하는 것이 왜 xargs잘못된 것입니까?find

귀하의 접근 방식에는 몇 가지 다른 문제가 있습니다.

  • -path venv-path고려 중인 파일의 전체 경로와 일치하는 항목 은 없으며 호출의 최상위 수준에서만 일치합니다 <contents-of-$1>/subdir/file. myfind venv ...나는 당신이 이라는 디렉토리에 저장된 파일을 무시하고 싶다고 가정합니다 venv. 이렇게 할 수는 있지만 ! -path '*/venv/*'나중에 디렉터리에 있는 모든 파일을 필터링하는 것보다 처음부터 해당 디렉터리에 들어가지 않도록 지시하는 것이 더 효율적입니다. (파일 경로가 로케일에서 유효한 텍스트가 아닌 경우에도 문제가 발생할 수 있습니다.) .find! -path '*/venv/*'

  • for , 당신은 의 두 번째에서 두 번째 인수를 형성하기 위해 현재 디렉토리에서 일치하는 파일 목록으로 myfind first *.py last확장하도록 쉘에 요청하고 있습니다. 이는 for 에 전달하여 after 에 전달 하려는 리터럴 인수 입니다 . 따라서 다음이 필요합니다. 쉘이 문자를 와일드카드로 해석하지 않도록 문자를 인용하십시오 . 여기서는 나머지 3개 문자( , 및 )가 쉘에 특별하지 않기 때문에 전체 내용을 while 또는 으로 인용하는 것으로 충분합니다 .*.pymyfind*.pymyfindmyfindfind-name**.py'*.py''*'.py\*.py.py

    bash 대신 zsh를 사용하는 경우 .NET alias myfind='noglob myfind'에서 이를 수행할 수 있습니다. 그러면 쉘 없이 확장 myfind할 수 있습니다 .myfind . *.py test*.py

  • "$1"분할+glob( , 아님 ) 을 방지하려면 매개변수 확장을 인용해야 합니다 $1.

  • -HGNU 확장자 가 없으면 find파일이 하나만 발견 되면 grep해당 경로가 인쇄되지 않으므로 일치하는 위치를 알 수 없습니다. grep지원되지 않는 구현 의 경우 추가 인수로 전달할 -H수 있습니다 ./dev/null-exec grep -ne "$3" -- /dev/null {} +

  • !non-standard 에 해당하는 표준(및 더 짧은) 항목을 참조하세요 -not.

  • with 로 시작 grep -n "$3"하면 옵션으로 처리됩니다 . 따라서 옵션 에 인수로 내용을 전달하십시오. 동일한 문제가 존재 하지만 안타깝게도 표준 솔루션은 없습니다. 차단된 콘텐츠 가 고려됩니다.$3-grep-e "$3"$3-efind "$1"find -- "$1"$1옵션find그것 으로 시작 -하지만 여전히 다음과 같이 처리됩니다.술부, 그러니까 말이 안 돼요. 예를 들어, !또는이라는 디렉터리 (도 문제가 될 수 있습니다. BSD는 find이를 지원하지만 GNU와 대부분의 다른 구현은 그렇지 않습니다. 대시로 시작하는 디렉터리를 전달하는 데 사용됩니다.find -f "$1"findfindmyfind ./-dir-starting-with-data- '*.py' pattern

  • sh코드에서 유일한 비표준 구문은 function name()함수 정의 구문입니다. ksh 구문은 function name {...;}, Bourne 이고 표준 bash구문은 입니다 name() {...;}. bash가끔 지원 되기도 하지만 function name() { ...; }이를 사용해야 할 실질적인 이유는 없습니다.

  • -type f고려사항만 추가했습니다정기적인장치 파일이나 fifo 내에서 검색을 시작 하고 싶지 않을 것이고 grep 디렉터리나 소켓에 대한 오류가 보고될 것이기 때문입니다. GNU를 사용하면 find이를 로 대체하여 -xtype f최종적으로 일반 파일로 확인되는 심볼릭 링크도 고려할 수 있습니다.

관련 정보