grep이 특수 파일 이름을 처리하도록 허용

grep이 특수 파일 이름을 처리하도록 허용

이름 에 txt공백이나 특수 문자(예: #.

가 있지만 가 없는 모든 항목을 나열하는 grep솔루션이 있습니다 .grep -L "cannot have" $(grep -l "must have" *.txt)must havecannot have

abc defg.txt예를 들어, 단 한 줄만 포함하는 파일이 있습니다 : must have.

따라서 일반적으로 grep 솔루션은 을 찾아야 abc defg.txt하지만 다음을 반환합니다.

grep: abc: No such file or directory
grep: defg.txt: No such file or directory

포함된 파일 이름에 대해서는 #grep 솔루션이 작동하지 않는다고 생각합니다.

누구든지 grep 솔루션을 수정하도록 도와줄 수 있나요?

답변1

만약에더 나아가고 싶다면 awk를 사용하여 한 번에 모든 작업을 수행할 수 있습니다.

awk 'function s(){if(a&&!b){print f}} FNR==1{s();f=FILENAME;a=b=0} 
  /must have/{a=1} /cannot have/{b=1} END{s()}' filepattern

최근 gawk의 경우 BEGINFILE 및 ENDFILE을 사용하여 단순화할 수 있습니다. (모든 awk 답변과 마찬가지로 -f를 사용하여 awk 명령을 파일에 넣을 수 있으며 대부분과 마찬가지로 원하는 경우 쉽게 Perl로 변환할 수 있습니다.)

답변2

이미 GNU 특정 옵션( )을 사용하고 있으므로 -L다음을 수행할 수 있습니다.

grep -lZ -- "must have" *.txt | xargs -r0 grep -L -- "cannot have"

아이디어는 -ZNUL로 구분된 파일 이름 목록을 인쇄하고 xargs -r0해당 목록을 두 번째 grep.

기본적으로 명령 대체는 공백, 탭 및 줄 바꿈(및 에서는 NUL)으로 zsh분할됩니다 . Bourne과 같은 쉘은 zsh분할로 인해 발생하는 각 단어에 대해 와일드카드 작업도 수행합니다.

다음을 수행할 수 있습니다.

IFS='
' # split on newline only
set -f # disable globbing
grep -L -- "cannot have" $(
    set +f # we need globbing for *.txt in this subshell though
    grep -l -- "must have" *.txt
  )

하지만 이렇게 하면 개행 문자가 포함된 파일 이름이 계속 깨집니다.

zsh(그리고 오직) 에서 zsh다음을 수행할 수 있습니다:

IFS=$'\0'
grep -L -- "cannot have" $(grep -lZ -- "must have" *.txt)

또는:

grep -L -- "cannot have" ${(ps:\0:)"$(grep -lZ -- "must have" *.txt)"}

답변3

대신 쉘 명령을 사용해 보십시오 find.grep

find . -name '*.txt' -print0 | xargs -0 -I{} sh -c 'grep -q "must have" -- "{}" && grep -L "cannot have" -- "{}"'

관련 정보