나는 종종 다음과 같은 명령을 실행합니다.
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은 q
uiet 모드에서 실행됩니다. 각 파일에는 반환 값만 사용됩니다. 그렇다면 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
할 수 있도록 하는 것입니다 .vim
xargs -0
zsh
0
bash
readarray -td ''
에서는 zsh
다음 작업도 수행할 수 있습니다.
vim ./**/*(...e['grep -q pattern $REPLY'])
(여기서 는 메소드 ...
와 같이 추가할 수 있는 추가 한정자를 나타냅니다 find
.)
그러나 이는 사용된 방법과 마찬가지로 파일당 하나의 호출이 실행되므로 속도가 상당히 느려진다는 것을 의미 find -exec grep -q pattern {} ';'
합니다 grep
.
zsh
--color=always
기본값에서 값을 바꾸고 변경 하면 -Z
첫 번째 접근 방식이 작동합니다 . 다른 쉘에서는 변수에 NUL 저장을 지원하지 않기 때문에 작동하지 않으며 사용하거나 비활성화해야 하는 분할을 초래하는 단어에 대한 파일 이름 생성도 수행합니다.IFS
IFS=$'\0'
IFS=$' \r\n\0'
$IFS
set -o noglob
set -f
찾기 결과를 반복하는 것이 왜 나쁜 습관입니까?find
안정적으로 발견된 파일 목록을 처리하는 방법에 대한 추가 정보를 제공합니다 .
답변3
두 가지 다른 방법:
- 결과를 빠른 수정 목록에 넣습니다.
find ... -exec grep -Hn {} + >results
vim -q results
아니면 청소부(sh는 아님)
vim -q <(find ... -exec grep -Hn {} +)
- 사용
:grep -R
및:Cfilter
:
vim
:grep -R ...
:packadd cfilter
:Cfilter[!]
관련 :help
명령을 참조하세요.
:cnext
어느 쪽이든 및 기타 명령을 사용하여 일치 항목을 탐색할 수 있습니다 :help quickfix
.