이름 에 txt
공백이나 #
.
가 있지만 없는 모든 파일을 나열하는 grep
솔루션이 있습니다 .grep -L "cannot have" $(grep -l "must have" *.txt)
must have
cannot 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"
-Z
NUL로 구분된 파일 이름 목록을 인쇄하고 해당 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" -- "{}"'