명령 `grep -Ilri foo. | xargs grep -i bar`는 생성된 경로에 공백이 없는 경우에만 작동합니다.

명령 `grep -Ilri foo. | xargs grep -i bar`는 생성된 경로에 공백이 없는 경우에만 작동합니다.

해당 단어가 포함된 모든 파일 foo과 해당 단어가 포함된 파일을 찾으려면 bar다음을 사용할 수 있습니다.

grep -Ilri foo . | xargs grep -i bar

(대소문자를 구분하지 않고 바이너리 파일을 제외합니다.)... 그러나 파일 경로가 다음과 같은 경우

/Users/myusername/Text Files

그러면 작동하지 않습니다. 왜냐하면 이제 xargs부품이

grep -i bar /Users/myusername/Text Files

하지만 실제로는 그럴 필요가 있다

grep -i bar "/Users/myusername/Text Files"

또는

grep -i bar /Users/myusername/Text\ Files

어떻게 작동하게 만들까요? (macOS Monterey에서).

답변1

grep널 바이트로 파일 이름을 구분하는 GNU의 -Z/ 옵션을 지원하고 --null(FreeBSD는 긴 --null변형만 지원) xargs널 바이트를 입력 구분 기호로 사용하는 옵션 -0(일부 있음)을 지원하는 경우 이를 사용하여 파일 이름을 --null안전하게 처리할 수 있습니다.

grep -Ilri --null foo . | xargs -0 grep -i bar

grep및 가 xargs이러한 비표준 옵션을 지원하지 않는 경우 (하지만 둘 다 표준 -r이 아님 -I) 다음을 사용할 수 있습니다 find.

find . -type f -exec grep -Iiq foo {} \; -exec grep -iq bar {} \; -print

현재 디렉터리에서 시작하는 파일을 찾고, 찾은 각 파일에 대해 grep"foo"가 포함되어 있는지 확인하기 위해 실행되고, 그렇다면 grep"bar"가 포함되어 있는지 확인하기 위해 다시 실행되고, 포함되어 있으면 인쇄합니다. 그것의 이름.

이는 매우 효율적이지는 않지만 안전하게 작동합니다.

답변2

fooUnix 시스템에서 POSIX 도구를 강제로 "해당 단어 와 그 안에 있는 단어가 포함된 모든 파일을 찾도록 "하려면(테스트되지 않음):bar

find . -type f -exec \
    awk '
        FNR==1 { x=y=0 }
        { $0 = tolower($0) }
        /foo/ { x=1 }
        /bar/ { y=1 }
        x && y { hits[FILENAME]; nextfile }
        END { for (fname in hits) print fname }
    ' {} +

또는 원하는 경우:

find . -type f -exec \
    awk '
        FNR==1 { x=y=0 }
        { $0 = tolower($0) }
        /foo/ { x=1 }
        /bar/ { y=1 }
        x && y && !seen[FILENAME]++ { print FILENAME; nextfile }
    ' {} +

위의 두 경우 모두 효율성을 위해 이를 지원하는 awk를 사용 nextfile하지만, 지원하지 않는 awk에서도 동일한 파일 이름을 여러 번 인쇄하지 않도록 코드를 작성합니다.

위의 내용은 하위 문자열이나 정규식 대 문자열 일치에 관심이 없다고 가정합니다.

관련 정보