Emacs의 디렉토리 / 하위 디렉토리에서 파일 내용을 재귀 적으로 검색 / grep하는 방법은 무엇입니까?


14

나는 꽤 오랫동안 Emacs를 사용하고 있으며 여전히 (프로젝트) 디렉토리 내에서 문자열을 (재귀 적으로) grep하는 가장 좋은 방법이 무엇인지 이해하지 못하고 결과를 dired 버퍼 또는 더 많은 것으로 표시합니다. 유용한 방법. 제발 깨달아주세요


helm-projectile-grep(헬멧 발사체가 설치된 경우) 명령 을 사용해 보셨습니까 projectile-grep?
Chakravarthy Raghunandan

내가 모르는 helmprojectile이지만 권장되는 도구입니다, 내가 설치하고 배울 것입니다.
Boris Stitnicky

예, 발사체는 명령으로 질문에서 언급 한 것을 쉽게 수행 할 수있는 패키지입니다 projectile-grep. 또한 helm패키지 를 설치하는 것이 좋습니다 . helm및 없이 이맥스를 실행하는 것을 상상할 수 없습니다 helm-projectile. helm-ag패키지 에서 흥미로울 수도 있습니다 (emacs에서 은색 검색기를위한 강력한 인터페이스를 제공합니다. 아마 grep이나 ack보다 빠릅니다).
Chakravarthy Raghunandan

2
질문이 향후 Google 및 포럼 검색 자에게 더 유용하고 찾기 쉬울 수 있도록 , 단어를 재귀 적 으로 포함하도록 질문 제목 을 수정 하고 범위를 제한하는 것을 고려하십시오 (예 : 디렉토리에서 파일 내용을 재귀 적으로 잡는 방법) / 서브 디렉토리 . 이것은 단지 예일뿐입니다. 대신 다른 것이 될 수 있습니다.
lawlist

1
지금까지 의견과 답변은 다양한 멋진 방법 으로이 작업을 수행하기위한 많은 패키지를 제안했지만, 단순함 M-x grep이 왜 필요한 것을하지 않는지는 귀하의 질문에서 볼 수 없습니다. 임의의 명령 줄을 제공 할 수 find있습니다. 재귀가 필요할 때 때때로 사용 합니다.
MAP

답변:


15

글쎄, 원래 질문은 언급하지 않았으므로 rgrep여기서 계속 지적하겠습니다. 이것은 이미 Emacs에 내장 된 가장 간단한 옵션이며, 대부분의 경우 충분하다고 생각했습니다.

설명서에서

Recursively grep for REGEXP in FILES in directory tree rooted at DIR.

검색은 쉘 패턴 FILES와 일치하는 파일 이름으로 제한됩니다.

그래서, 예를 들어,의 용도로 홈 디렉토리 아래의 모든 파이썬 파일을 검색하기 위해 some_function내가 그것을 부를 것이다, some_function, *.py, ~/인수한다. 결과는 새로운 버퍼에 표시됩니다.


1
find-grep-diredOP가 언급 한 "결과는
끔찍한

내가 사용하지 않은 @npostavs find-grep-dired, 답변에 자유롭게 추가하십시오.
user2699

나는 ackrep에서 agrep을 사용하여 무언가로 전환해야한다는 가정하에 ack과 ag와 같은 실험을 한 적이 있었다. 결국 나는 변경에 대한 이점을 찾지 못했기 때문에 rgrep에 머물렀다! 커맨드 라인에는 분명한 경우가 있지만 Emacs rgrep에서는 검색을 타겟팅하는 데 상당한 속도 차이가 없었습니다. ( 어떤 경우에는 rgrep이 부분적으로 빠르다고 말하고 싶지만 확실하지 않습니다.)
phils

1
참고 next-errorprevious-error결과 집합을 탐색하는 데 사용할 수 있습니다. 내가 발견 M-g M-nM-g M-p표준 바인딩의 가장 편리한.
phils

find-grep-dired상호 참조 링크가있는 버퍼를 제공하지 않습니다. rgrep나를 위해 그것을하고 마지막 제안 next-error previous-error은 환상적입니다! 내 유일한 퀴즈는 버퍼 시작시 모든 지저분한 명령 실행이 출력된다는 것입니다.
robert

11

나는 M-x find-grep-dired수년간 행복하게 사용 합니다. 사용 가능한 dired 버퍼로 결과를 반환합니다.


이 작업을 위해 상호 참조 링크를 얻는 데 어려움이있었습니다. 구성이 매우 불쾌하고 ( find-ls-option) 결국 파일 이름 앞에 날짜가 없으면 작동하지 않기 때문에 매우 장황한 것으로 끝납니다!
robert

5

솔루션 1 (최상의 솔루션) :

상담 설치 ( https://github.com/abo-abo/swiper/blob/master/counsel.el )

그런 다음 M-x counsel-git-grep.

설정이 필요하지 않습니다 (git은 프로젝트 루트와 제외 할 파일을 알고 있습니다). 모두 git grepcounsel효율적이다.

프로젝트는 git에 의해 관리되어야합니다.

상담에는 아이비 모드가 필요합니다.

해결책 2 :

이 솔루션은 grep을 사용하며 모든 프로젝트에서 작동합니다. 속도가 느리고 수동 설정이 필요하므로 솔루션 1보다 열등합니다. 또한 아이비 모드를 기반으로합니다.

(defvar simple-project-root "~/.emacs.d")
(defun simple-grep ()
  (interactive)
  (unless (featurep 'ivy)
    (require 'ivy))
  (let* ((default-directory (file-name-as-directory simple-project-root))
         (keyword (read-string "Keyword:")))
    (ivy-read (format "Grep at %s:" simple-project-root)
              (split-string (shell-command-to-string (format "grep -rsnI %s ." keyword)) "\n" t)
              :action (lambda (val)
                        (let* ((lst (split-string val ":"))
                               (linenum (string-to-number (cadr lst))))
                          ;; open file
                          (find-file (car lst))
                          ;; goto line if line number exists
                          (when (and linenum (> linenum 0))
                            (goto-char (point-min))
                            (forward-line (1- linenum))))))))

설정하려면 .dir-locals.el을 만들어야합니다. 자세한 기술 정보는 https://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.htmlsimple-project-root참조 하십시오.

솔루션 2의 코드는 단지 프로토 타입입니다. 내 실제 구현은 훨씬 더 복잡합니다. 보기 counsel-etags-grephttps://github.com/redguardtoo/counsel-etags/blob/master/counsel-etags.el

요약:

이것이 내가 아는 최고의 두 가지 솔루션입니다.

다른 더 나은 솔루션이 존재하면 프로덕션 준비가 되려면 최소한 아래의 문제를 해결해야합니다.

  • 키워드를 grep하는 방법 (예 : 선택한 지역에서 키워드 가져 오기)

  • 키워드를 피하십시오

  • 보다 효율적인 grep 프로그램이 존재하면이를 사용하거나 (ripgrep, the_silver_searcher / ag 등) 기본 grep을 대체해야합니다.

  • 후보 창은 전체 화면을 사용해야하며 사용자는 대화식으로 후보를 필터링 할 수 있습니다 (그러므로 사람들이 아이비 또는 투구를 사용하는 이유)

  • 후보 창에 상대 경로를 표시해야합니다

  • 이전에 잘린 결과를 재사용 할 수 있습니다. 따라서 이전 결과를 저장해야합니다. 당신은 사용할 수 있습니다 ivy-resume에서 ivy또는 helm-resume에서helm

  • 이전에 잘린 결과를 저장할 때 이전 결과의 컨텍스트도 저장해야합니다. 예를 들어 솔루션 2의 코드에는 default-directory컨텍스트가 있습니다. 자세한 내용은 https://github.com/abo-abo/swiper/issues/591 을 참조하십시오.

  • 확장 정규 표현식은 더 단순하고 counsel-git-grepthe_silver_searcher / ag에서 이미 사용하기 때문에 사용해야합니다 .


4

@chen bin의 솔루션에 다른 솔루션을 추가하고 싶습니다 counsel(그러나 git이것을 위해 프로젝트를 유지할 필요는 없습니다 ).

ag (실버 검색기) 를 설치 하고 현재 디렉토리에서 입력 한 문자열을 검색하는 counsel명령 counsel-ag을 제공해야 합니다.

현재 작업 디렉토리뿐만 아니라 프로젝트 내에서 검색하려면 다음을 추가하십시오 .emacs.

  (defun rag/counsel-ag-project-at-point ()
    "use counsel ag to search for the word at point in the project"
    (interactive)
    (counsel-ag (thing-at-point 'symbol) (projectile-project-root)))

이 함수는 ag프로젝트 루트 디렉토리를 재귀 적으로 검색하는 데 사용 됩니다.

편집 : 위의 기능은 검색 할 때 기호로 기본 설정됩니다. 당신이 행동을 같이하지 않으면, 교체 (thing-at-point 'symbol)와 함께 nil. 검색 결과를 원한다면 자체 버퍼 프레스C-c C-o

EDIT2가 : 당신이 한 경우 ripgrep설치, 당신은 대체 할 수 counsel-agcounsel-rg위의 기능과는 잘 예정대로거야 :)


projectile-project-root레일 프로젝트 루트를 찾을 가능한?
Boris Stitnicky

예, 유효한 발사체 프로젝트라면 작동합니다. 내가 생각하는 발사체 레일이라는 패키지가있었습니다.
Chakravarthy Raghunandan

왜 함수의 이름을 지정 했 rag/...습니까?
Boris Stitnicky

사람들이 자신의 함수를 작성할 때 자주 사용하는 일반적인 스타일입니다 (emacs 구성을 탐색하면 다른 사람들이 수행하는 것을 볼 수 있습니다). 모든 기능은 I로 시작 정의 rag/접두사와 그 아래에 쉽게 찾을 수 있습니다을하게 M-x:)
Chakravarthy Raghunandan을

Ic, 그것은 당신의 이름입니다 :-)
Boris Stitnicky

2

다음은 디렉토리 및 서브 디렉토리에서 파일 내용 (검색 용어에 regexp 사용)을 재귀 적으로 파악하고 결과를 컨텍스트 전후에 표시하는 사용자 정의 grep 함수의 예입니다. 내장 compile.elgrep.el라이브러리는 검색 결과가 포함 된 파일의 위치로 이동할 수있는 몇 가지 방법을 제공합니다. 이 예제가 작동하기 위해 다른 것을 설치할 필요는 없습니다. 필요한 것은 정식 버전의 Emacs와 grep유틸리티가 설치된 컴퓨터뿐입니다 . 기본값이 충분하지 않은 경우 유틸리티 grep-program의 특정 위치를 가리 키도록 변수 를 조정할 수 있습니다 grep.

(defun recursive-grep ()
"Recursively grep file contents.  `i` case insensitive; `n` print line number;
`I` ignore binary files; `E` extended regular expressions; `r` recursive"
(interactive)
  (let* ((search-term (read-string "regex:  "))
         (search-path
           (directory-file-name (expand-file-name (read-directory-name "directory:  "))))
         (default-directory (file-name-as-directory search-path))
         (grep-command
           (concat
             grep-program
             " "
             "-inIEr --color=always -C2"
             " "
             search-term
             " "
             search-path)))
    (compilation-start grep-command 'grep-mode (lambda (mode) "*grep*") nil)))

문제는 동시에 위 그렙 기능에 의한 결과로 반환됩니다 여러 파일을 수정하는 방법을 추구하지 않지만, 나는 그것이 매우 도움이 사용할 찾아 multiple-cursorswgrep. 한 번에 여러 파일을 수정하는 것이 쉬워졌습니다. 그러나 해당 기능이 필요한 경우 해당 라이브러리를 설치해야합니다.
lawlist

내장보다 이것을 사용하면 어떤 이점이 rgrep있습니까?
npostavs

1
@npostavs- rgrep기본 제공 정규식 검색 기준에 맞게 사용자 정의하는 데 시간이 오래 걸리고 모든 것을 사용자 정의 함수 (매일 여러 번 사용)로 하드 코딩하기로 결정했습니다. 을 사용자 정의하는 방법을 설명하는 대체 답변을 작성 rgrep하려면 나중에 다른 포럼 독자에게 도움이 될 것입니다.
lawlist
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.