특정 경로에서 파일을 제외하고`grep`을 실행하십시오.


12

./test/main.cpp검색 에서 파일을 제외하고 싶습니다 .

내가보고있는 것은 다음과 같습니다.

$ grep -r pattern --exclude=./test/main.cpp
./test/main.cpp:pattern
./lib/main.cpp:pattern
./src/main.cpp:pattern

파이프 및 필터 배열에서 여러 명령을 사용하여 원하는 출력을 얻을 수 있지만 grep기본적으로 원하는 것을 이해하는 인용 / 이스케이프가 있습니까?


출력 필터링을 기반으로하는 솔루션은 관련 결과를 제외하기 전에 파일을 불필요하게 검색하므로 확장 성이 떨어집니다. 로 전체 디렉토리를 제외하려는 경우 문제가 확대됩니다 --exclude-dir. 그래서 grep이 기본적으로 제외를 수행하도록하고 싶습니다.
nobar

1
--exclude는 경로가 아닌 glob를 지정합니다.
PersianGulf

답변:


6

grep 다른 디렉토리에 동일한 이름을 가진 파일이 더있는 경우 특정 디렉토리의 파일에 대해이 작업을 수행 할 수 없습니다. 대신 find를 사용하십시오.

find . -type f \! -path './test/main.cpp' -exec grep pattern {} \+


왜 탈출 \!하고 \+있습니까? 백 슬래시없이 잘 작동하는 것 같습니다.
nobar

@nobar 일부 문자는 쉘 키워드이기 때문에 익숙해 져서 탈출하면 아무런 일도 일어나지 않으므로 놀라지 않을 것입니다.
MichalH

" grep이 작업을 수행 할 수 없습니다 find. 대신 사용하십시오 ."-완벽합니다.
nobar

4

나는 그것이 GNU에서 가능하다고 생각하지 않습니다 grep. 파이프는 필요하지 않습니다.

find:

find . ! -path ./test/main.cpp -type f -exec grep pattern {} +

zsh:

grep pattern ./**/*~./test/main.cpp(.)

(숨겨진 파일은 제외하고 .git, .svn ...도 제외합니다.)


2

나는 "잃어버린 예술"이라는 책을 쓸 수있었습니다 xargs. find ... -exec … ';출시 각 파일에 대한 그렙 (그러나와 변형 -exec … +하지 않습니다). 요즘 우리는 CPU 사이클을 낭비하고 있습니다. 왜 그렇지 않습니까? 그러나 성능과 메모리 및 전원이 문제인 경우 xargs를 사용하십시오.

find . -type f \! -path 'EXCLUDE-FILE' -print0 | xargs -r0 grep 'PATTERN'

GNU의 find의는 -print0것이다 NUL출력 및 -terminate xargs' -0입력으로 해당 형식 옵션 명예를. 이렇게하면 파일에 재미있는 문자가 있으면 파이프 라인이 혼동되지 않습니다. 이 -r옵션은 find아무것도 찾지 못할 경우 오류가 없는지 확인 합니다.

이제 다음과 같은 작업을 수행 할 수 있습니다.

find . -type f -print0 | grep -z -v "FILENAME EXCLUDE PATTERN" | 
  xargs -r0 grep 'PATTERN'

GNU grep 's -z는 xargs '와 동일한 기능을 수행합니다 -0.


3
몇 가지 흥미로운 메모가 있지만 성능 문제가 올바른지 잘 모르겠습니다. 나는 그것을 이해 find -exec (cmd) {} +와 동일하게 작동 xargsfind -exec (cmd) {} \;같은 작동합니다 xargs -n1. 즉, \;버전이 사용 된 경우에만 진술이 정확합니다 .
nobar

3
파이핑 xargs은 사용하는 것보다 덜 효율적 -exec … +입니다. 여기에 대한 답변도 언급되지 않았습니다 -exec … \;.
Gilles 'SO- 악마 중지

1
글쎄요. 나는 나 자신과 데이트한다. 의견과 수정에 감사드립니다. 나는 \ +가 오타라고 생각했다. 오, -exec ... +2005 년 1 월에 추가 됐습니다. 그래, 난 구식이 아니 었어 ... 전혀 ..
테우스

2

귀하의 경우에는 find지원 -path2008 년 POSIX에 추가하지만 여전히 솔라리스에서 누락되었다 :

find . ! -path ./test/main.cpp -type f -exec grep pattern /dev/null {} +

1
나는 nobar가 다른 디렉토리에있는 main.cpp를 원하기 때문에 그것이 효과가 없을 것이라고 생각한다
Eric Renouf

1
패턴이 다른 모든 디렉토리에서도 main.cpp를 제외하지 않습니까? 바람직하지 않을 것입니다
Eric Renouf

@EricRenouf : 오, 내 실수, 오독. 내 답변을 업데이트했습니다.
cuonglm

@Gilles : -pathPOSIX가 아닌 이유 는 무엇 입니까?
cuonglm

아, 죄송합니다. 제 실수는 2008 년에 추가 된 것입니다. 그래도 Solaris에서 누락되었습니다.
Gilles 'SO- 악마 그만해'

1

기록을 위해, 내가 선호하는 접근 방식은 다음과 같습니다.

grep pattern $(find . -type f ! -path './test/main.cpp')

grep명령의 시작 부분에 를 유지하면 이것이 더 명확하다고 생각합니다 grep. 또한 색상 강조 표시를 비활성화하지 않습니다 . 어떤 의미 find에서, 명령 대체에서 사용 하는 것은 기능의 (제한된) 파일 검색 서브 세트를 확장 / 대체하는 방법입니다 grep.


나에게 find -exec구문 은 일종의 비전입니다. 한 가지 복잡한 점 find -exec은 (때로는) 다양한 문자를 피할 필요가 있다는 것입니다 (특히 \;Bash에서 사용되는 경우 ). 익숙한 상황에 적용하기 위해 다음 두 명령은 기본적으로 동일합니다.

find . ! -path ./test/main.cpp -type f -exec grep pattern {} +
find . ! -path ./test/main.cpp -type f -print0 |xargs -0 grep pattern

하위 디렉토리제외 하려면 와일드 카드를 사용해야 할 수도 있습니다. 나는 완전히 여기 스키마를 이해하지 않는 - 비밀에 대한 이야기 :

grep pattern $(find . -type f ! -path './test/main.cpp' ! -path './lib/*' )

스크립트에서 사용하기위한find 기반 솔루션 을 일반화 하기위한 추가 참고 사항 : grep명령 행에는 -H/ --with-filename옵션 이 포함되어야합니다 . 그렇지 않으면의 검색 결과에 파일 이름이 하나만있는 상황에서 출력 형식이 변경됩니다 find. grep의 기본 파일 검색 ( -r옵션 포함)을 사용하는 경우 필요하지 않은 것 같으므로 주목할 만합니다 .

...하지만 /dev/null검색 할 첫 번째 파일로 포함 시키는 것이 더 좋습니다 . 이렇게하면 두 가지 문제가 해결됩니다.

  • 검색 grep할 파일이 하나 있으면 두 개가 있다고 생각하고 다중 파일 출력 모드를 사용합니다.
  • 검색 할 파일이 없으면 grep하나의 파일이 있다고 생각하고 stdin을 기다리지 않습니다.

최종 답변은 다음과 같습니다.

grep pattern /dev/null $(find . -type f ! -path './test/main.cpp')

find명령 대체에서 의 출력을 사용해서는 안됩니다 . 공백이나 다른 특수 문자가 포함 된 파일 이름이 있으면 중단됩니다. 사용 find -exec, 그것은 사용하기 쉽고 강력하고 있습니다.
Gilles 'SO- 악마 그만해

@Gilles : 아주 좋은 점-또한 출력은 일부 프로그램의 명령 줄 크기 제한을 초과 할 수 있습니다. 주의 사항
nobar

어. '찾기'구문은 매우 어렵습니다. '-o'는 "or"연산자 (리눅스에서는 '-or')이지만 일반적인 사용법 (예 : '-prune')은 개념적으로 논리 또는 개념에 매핑되지 않습니다. 논리적이거나 논리적이지 않고 기능적입니다.
nobar

이름 일치를 기반으로 하위 디렉토리를 제외하는 또 다른 방법 : find -iname "*target*" -or -name 'exclude' -prune. 자, 그것은 일종의 작품입니다-정리 된 디렉토리는 나열되지만 검색되지는 않습니다. 목록을 원하지 않으면, 중복을 추가 할 수 있습니다! -name 'exclude'
nobar
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.