특수 파일 이름에 대해 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" -- "{}"'

관련 정보