find … -exec grep … {} \+ 결과로 제공되는 파일을 여는 안정적인 방법

find … -exec grep … {} \+ 결과로 제공되는 파일을 여는 안정적인 방법

나는 종종 다음과 같은 명령을 실행합니다.

find … -exec grep … --color=always -l {} \+

때로는 Vim에서 일치하는 파일을 열어야 할 때가 있습니다.

그런데 가장 확실한 방법은 무엇일까요?

일방 통행그런 것 같다

vim $(find … -exec grep … {} \+)

또 다른 접근 방식은 xargs.

이 두 가지 방법과 다른 방법에 대해 알아야 할 장점/단점/문제가 있습니까?

답변1

vim $(find path/ -exec grep -l 'pattern' {} +)

따옴표가 없는 명령 대체이므로 결과의 공백과 경로 이름 확장에 대해 토큰화가 수행됩니다. 즉, 파일이 a b일치하면 Vim은 잘못 열리고 a. b파일이 * 일치하면 아쉽게도 해당 디렉터리의 모든 파일로 확장됩니다. 적합한 솔루션은

find path/ -type f -exec grep -q 'pattern' {} \; -exec vim {} +

Grep은 quiet 모드에서 실행됩니다. 각 파일에는 반환 값만 사용됩니다. 그렇다면 0파일에서 일치하는 항목을 찾아 해당 파일을 Vim으로 전달합니다.

{} \;Grep이 한 번에 하나의 파일을 분석함을 나타냅니다. {} +모든 파일은 Grep에 인수로 전달되며 다음을 사용하면 일치하는 항목이 발견됩니다.어느이러한 파일 수에 따라 0종료 상태가 발생하므로 모든 파일이 Vim에서 열립니다. 반면 {} +에 Vim의 경우 발견된 각 파일이 단일 Vim 프로세스의 버퍼에 저장됩니다. 변화를 느끼기 위해 변화를 시도해 볼 수 있습니다.

작업 속도를 높여야 하는 경우:

  • 'pattern'정규식이 아니고 고정된 패턴이라면 Grep -F에 플래그를 추가하세요.

  • grep -lZ, Xargs 및 특수 쉘 구성도 프로세스 속도를 높여야 합니다.Stefan Chazeras의 답변.

그리고여기Xargs, Find 및 Vim의 또 다른 유사한 사용 사례입니다.

답변2

GNU 도구( --color=always이미 GNU 확장임)와 Ksh 스타일 프로세스 교체를 지원하는 셸 사용:

xargs -r0a <(grep -rlZ pattern .) vim

또는:

xargs -r0a <(find . ... -exec grep -lZ pattern {} +) vim

그리고 zsh:

vim ${(0)"$(find . ... -exec grep -lZ pattern {} +)"}

4.4+ 버전 bash:

readarray -td '' files < <(find . ... -exec grep -lZ pattern {} +)
vim "${files[@]}"

이렇게 하면 grep수행되는 호출 수가 최소화됩니다. 요점은 출력을 NUL로 구분된 파일 이름으로 지정하여 GNU 의 인수 확장 플래그를 통해 별도의 인수로 안정적으로 분할 grep할 수 있도록 하는 것입니다 .vimxargs -0zsh0bashreadarray -td ''

에서는 zsh다음 작업도 수행할 수 있습니다.

vim ./**/*(...e['grep -q pattern $REPLY'])

(여기서 는 메소드 ...와 같이 추가할 수 있는 추가 한정자를 나타냅니다 find.)

그러나 이는 사용된 방법과 마찬가지로 파일당 하나의 호출이 실행되므로 속도가 상당히 느려진다는 것을 의미 find -exec grep -q pattern {} ';'합니다 grep.

zsh--color=always기본값에서 값을 바꾸고 변경 하면 -Z첫 번째 접근 방식이 작동합니다 . 다른 쉘에서는 변수에 NUL 저장을 지원하지 않기 때문에 작동하지 않으며 사용하거나 비활성화해야 하는 분할을 초래하는 단어에 대한 파일 이름 생성도 수행합니다.IFSIFS=$'\0'IFS=$' \r\n\0'$IFSset -o noglobset -f

찾기 결과를 반복하는 것이 왜 나쁜 습관입니까?find안정적으로 발견된 파일 목록을 처리하는 방법에 대한 추가 정보를 제공합니다 .

답변3

두 가지 다른 방법:

  1. 결과를 빠른 수정 목록에 넣습니다.
find ... -exec grep -Hn {} + >results
vim -q results

아니면 청소부(sh는 아님)

vim -q <(find ... -exec grep -Hn {} +)
  1. 사용 :grep -R:Cfilter:
vim
:grep -R ...
:packadd cfilter
:Cfilter[!]

관련 :help명령을 참조하세요.

:cnext어느 쪽이든 및 기타 명령을 사용하여 일치 항목을 탐색할 수 있습니다 :help quickfix.

관련 정보