Emacs를 사용하여 아직 열지 않은 텍스트 파일에서 재귀 적으로 찾기 및 바꾸기


212

이 질문에 대한 후속 조치로 , 쉽게 해야하는 이와 같은 일을하는 방법을 찾으려고 노력하고 있습니다. 특히 Emacs 사용에 익숙해지지 않고 대신 이미 익숙한 편집기를 시작하지 못하게합니다. 여러 파일을 편집 할 때 여기 예제를 상당히 자주 사용합니다.

Ultraedit에서 Alt + s를 누른 다음 p를 사용하여 찾기 (여러 줄에 정규식 사용 포함), 바꾸기, 파일 / 유형, 디렉토리, 대소 문자 구분, 전체 단어 만 일치, 목록 옵션이있는 대화 상자를 표시합니다. 변경된 파일 및 검색 하위 디렉토리. 일반적으로 먼저 마우스를 사용하여 바꾸려는 텍스트를 클릭-드래그합니다.

외부 유틸리티를 호출하지 않고, (Windows XP에서)에만 이맥스 자체를 사용하는 방법에 바 \ nbaz 모든 foo는 \ NBAR을 교체 *.c하고 *.h일부 폴더에있는 파일 및 폴더 그 아래. 어쩌면 Emacs가 가장 좋은 도구는 아니지만 최소한의 명령으로 쉽게 수행 할 수 있습니까?

답변:


370
  1. M-x find-name-dired: 루트 디렉토리와 파일 이름 패턴을 묻는 메시지가 나타납니다.
  2. t발견 된 모든 파일에 대해 "토글 표시"를 누르십시오 .
  3. Q"파일에서 쿼리 바꾸기 ..."를 누르십시오 : 쿼리 / 대체 정규 표현식을 입력하라는 메시지가 나타납니다.
  4. 다음과 같이 진행합니다 query-replace-regexp: SPACE다음 경기로 교체 및 이동 n, 경기 건너 뛰기 등.
  5. C-x s버퍼를 저장하려면 누릅니다 . (그런 다음 Enter 키를 눌러 수 있습니다 y, n또는 !한 번에 모든 내용을 저장합니다)

10
아니요, 재귀입니다. 비 재귀 버전은 dired 모드에서 % m입니다.
Chris Conway

5
아마도 GNU find가 아닌 C : \ WINDOWS \ system32 \ find.exe를 호출했기 때문일 수 있습니다.
재즈

6
Steen, Chris : 아마도 정확히 원하는 것은 아니지만 'Cx s'(Save-some-buffers)를 사용할 수 있습니다. 수정 된 파일마다 프롬프트가 표시되므로 'y'를 여러 번 눌러야합니다.
danielpoe 2016 년

48
C-x s !모든 파일을 한 번에 저장합니다.
cYrus

10
M-,검색 및 교체를 계속하려면 (예 : 디스크에서 파일이 변경된 경우 "파일 되돌리기"프롬프트 후)
tfischbach

37
  • M-x find-name-dired RET
    • 모든 파일이 목록에 나타날 M->때까지 시간이 걸릴 수 있습니다. " find finished"가 나타날 때까지 맨 아래 ( )로 스크롤하여 파일이 모두로드되었는지 확인하십시오.
  • t발견 된 모든 파일에 대해 "토글 표시"를 누릅니다.
  • Q"파일에서 쿼리 바꾸기 ..."를 누르십시오 : 쿼리 / 대체 정규 표현식을 입력하라는 메시지가 나타납니다.
  • query-replace-regexp : SPACE와 같이 진행하거나 y다음 일치로 바꾸고 다음 일치로 이동하고 일치를 건너 뛰려면 n을 입력하십시오.
    • 입력! 묻지 않고 현재 파일의 모든 발생을 바꾸고 N, 현재 파일의 나머지 부분에 대한 가능한 모든 대체를 건너 뜁니다. ( Nemacs 23+ 만 해당)
    • 더 이상 묻지 않고 모든 파일을 바꾸려면을 입력하십시오 Y.
  • 열려있는 모든 파일을 나열 C-x C-b하려면 "ibuffer"(ibubu에 바인딩 된 경우 또는 M-x ibuffer RET)를 호출 하십시오.
  • * u저장하지 않은 모든 파일을 표시하려면 입력 하고 표시된 모든 파일 S을 저장하려면 입력 하십시오
  • * * RET모든 표시를 해제하거나 D표시된 모든 파일을 닫으려면 입력

이 답변은 이 답변 , 이 사이트 및 내 메모에서 결합됩니다. 이맥스 사용 23+.


3
ibufferC-x C-b기본적으로 바인딩되어 있지 않습니다 .
phils

2
개인적으로는 사람들 이에 바인딩 C-x C-b하는 것이 좋습니다 ibuffer. 기본 바인딩보다 훨씬 낫기 때문입니다. (global-set-key (kbd "C-x C-b") 'ibuffer).emacs 파일에 추가 하십시오. 실패 M-x ibuffer RET하면 위의 지침에 따라 사용하십시오.
phils

확인. 나는 emacs 스타트 업 키트를 가지고 있다고 생각한다. 이것이 내 바운드이다
Frank Henard

1
파일 bla-bla-bla이 읽기 전용으로 방문되어 검색을 중지합니다. 그것을 피하고 무시하고 교체하는 방법? 감사.
Felipe

3
왜 ( )하고 입력 ibuffer할 수 있습니까? 나는 화를 내고 싶지 않고 그냥 궁금합니다. PS 플러스 설명하기위한 , 그리고 . C-x ssave-some-buffers!!NY
d12frosted

17

제공된 답변은 훌륭하지만 약간 다른 접근법을 추가 할 것이라고 생각했습니다.

그것은 더 상호 작용하는 방법, 그리고 필요 wgrep, rgrepiedit. 모두 ieditwgrepMELPA 또는 마멀레이드 (사용을 통해 설치해야합니다 M-x package-list-packages)

먼저 M-x rgrep원하는 문자열을 찾기 위해 실행 하십시오.

파일 형식 / 패턴 및 재귀 폴더를 지정할 수 있습니다.

다음으로 wgrep시작해야합니다 C-s C-p.

Wgrep 당신이 편집 할 것이다 rgrep결과를, 그래서 일치 시작하는 문자열에 영역을 설정 iedit-mode하여 C-;(당신이 다시 바인딩이해야 할 수도 있습니다 터미널에 따라 다름)

모든 항목을 한 번에 편집 할 수 있습니다. C-x C-s커밋 wgrep합니다. 그런 다음 C-x s !변경된 파일을 저장하십시오.

이 방법의 주요 이점은 iedit-mode특정 일치 항목을 끄는 데 사용할 수 있다는 것 M-;입니다. rgrep예를 들어 예기치 않은 일치 항목이있는 경우 결과를 사용하여 파일로 이동할 수 있습니다.

프로젝트 전체에서 소스 편집 및 심볼 이름 바꾸기 (변수, 함수 이름 등)를 수행하는 데 매우 유용합니다.

iedit 모드를 모르거나 사용하지 않는 경우 매우 유용한 도구이므로 살펴 보는 것이 좋습니다.


이 기술은 iedit를 사용하지 않아도 매우 강력합니다. grep하는 방법을 알면 (lgrep / rgrep으로 쉽게) 대량 검색 대체 방법을 알 수 있습니다!
NeilenMarais

rgrep / wgrep / macros를 결합하는 것은 대단합니다.
ocodo

2
시작할 키 바인딩 wgrepC-c C-pbtw입니다.
techniao

15

발사체는 정말 좋습니다 : Cc pr은 발사체 교체 명령을 실행합니다


13

필자는 일반적으로 다른 도구를 사용하여이 작업을 수행하며 EmacsWiki의 파일 간 찾기 및 바꾸기 항목 셸 에서 언급 한 많은 접근 방식 처럼 보이지만 Finder 패키지 는 매우 유망합니다.

소스 파일의 일부를 훔치기 :

(defun findr-query-replace (from to name dir)
  "Do `query-replace-regexp' of FROM with TO, on each file found by findr.

findr.el을 사용하여 java 및 hxx 확장자를 가진 모든 파일에서 문자열 "Collectible"을 찾으려면 어떻게합니까?
swdev

@swdev : Mx findr-query-replace RET 수집 가능한 RET <대체> RET. * \. java RET <검색을 시작할 디렉토리> RET
ShreevatsaR

나는이 접근법을 좋아한다 (직접적인 접근법과 관련된 모든 토글을 피한다). 나는 편리한 기능을 사용하여 이것을 발사체 (project-root-discover)와 결합하고 그 지점을 대체합니다 : gist.github.com/anonymous/055a9d62f9fc824153599724b8f44d57
Att Righ

6

정보 출처 : 1

emacs pro 사용자의 경우 :

  1. dir에 파일을 나열하려면 dired를 호출하거나 모든 하위 디렉토리가 필요한 경우 find-dired를 호출하십시오.
  2. 원하는 파일을 표시하십시오. 【% m】을 입력하여 정규식으로 표시 할 수 있습니다.
  3. dired-do-query-replace-regexp를 호출하려면 Q를 입력하십시오.
  4. 찾기 정규식을 입력하고 문자열을 바꿉니다. 〔☛ 공통 elisp 정규식 패턴〕
  5. 각 발생에 대해 교체하려면 y를 입력하고 건너 뛰려면 n을 입력하십시오. 전체 조작을 중단하려면 [Ctrl + g]를 입력하십시오.
  6. 입력! 묻지 않고 현재 파일의 모든 항목을 바꾸려면 N은 현재 파일의 나머지 부분에 대한 가능한 모든 교체를 건너 뜁니다. (N은 이맥스 23 만 해당)
  7. 더 이상 묻지 않고 모든 파일을 바꾸려면 Y를 입력하십시오 (Emacs 23 만 해당).
  8. 열려있는 모든 파일을 나열하려면 ibuffer를 호출하십시오. 저장하지 않은 모든 파일을 표시하려면 【* u】를 입력하고 표시된 파일을 모두 저장하려면 S를 입력하고 모두 닫으려면 D를 입력하십시오.

Emacs 초보자를위한 단계별 안내서

대상 파일 선택

명령 행 인터페이스 프롬프트에 "emacs"를 입력하여 emacs를 시작하십시오. 또는 그래픽 사용자 인터페이스 환경에있는 경우 Emacs 아이콘을 두 번 클릭하십시오.

디렉토리에서 파일 선택

먼저 교체하려는 파일을 선택해야합니다. 그래픽 메뉴 〖파일 ▸ 디렉토리 열기〗를 사용하십시오. Emacs는 디렉토리 경로를 묻습니다. 디렉토리 경로를 입력 한 후 Enter를 누르십시오.

이제 파일 목록이 표시되고 정규식 찾기 / 바꾸기를 원하는 파일을 표시해야합니다. 커서를 원하는 파일로 이동하여 파일을 표시 한 다음 m을 누르십시오. u를 눌러 표시를 해제하십시오. (하위 디렉토리를 나열하려면 커서를 디렉토리로 이동하고 i를 누릅니다. 하위 디렉토리의 내용이 맨 아래에 나열됩니다.) 모든 파일을 정규식으로 표시하려면 【% m】을 입력 한 다음 정규식 패턴을 입력하십시오. 예를 들어 모든 HTML 파일을 표시하려면 【% m】을 입력 한 다음 .html $을 입력하십시오. 그래픽 메뉴 "Mark"에서 마크 명령 목록을 찾을 수 있습니다 (이 메뉴는 다이어 드 모드에있을 때 나타납니다).

디렉토리 및 모든 하위 디렉토리에서 파일 선택

수백 개의 서브 디렉토리를 포함하여 디렉토리 내의 파일을 찾거나 바꾸려면이 파일을 모두 선택하는 방법이 있습니다.

찾기에 전화하십시오. ([Alt + x]를 눌러 명령을 호출합니다.) 그런 다음 디렉토리 이름을 입력하십시오. ⁖ / Users / mary / myfiles

참고 : 유닉스 그래픽이 아닌 텍스트 터미널에서 emacs를 사용하는 경우, [Alt + x]가 작동하지 않으면, 동등한 키 입력은 [Esc x]입니다.

Emacs는“Run find (args) :”프롬프트를 표시합니다. 모든 HTML 파일을 교체해야하는 경우 -name "* html"을 입력하십시오. 어떤 종류의 파일에 신경 쓰지 않고 단순히 그 디렉토리 아래의 모든 파일에 신경 쓰면“-type f”를 지정하십시오.

이제 위에서 설명한대로 파일을 표시하십시오.

대화식 찾기 / 바꾸기

이제 대화식 찾기 교체를 수행 할 준비가되었습니다. 간단히하기 위해“quick”이라는 단어를“super”로 바꾸고 싶다고 가정 해 봅시다. 이제 dired-do-query-replace-regexp를 호출하십시오. 정규식 문자열과 교체 문자열을 묻는 메시지가 나타납니다. "quick"을 입력하고 입력 한 다음 "super"를 입력하십시오.

이제 emacs는 패턴을 사용하여 파일을 확인하고 일치하는 것이 발생할 때마다 중지하고 표시합니다. 이런 일이 발생하면 emacs가 프롬프트를 표시하며 변경을 선택하거나 건너 뛸 수 있습니다. 변경하려면 y를 입력하십시오. 건너 뛰려면 n을 입력하십시오. emacs를 계속 진행하고 현재 파일을 모두 변경하려면!를 입력하십시오.

변경 사항을 저장하지 않고 전체 작업을 취소하려면 [Ctrl + g]를 입력 한 다음 메뉴 〖파일 ▸ 종료 Emacs〗를 사용하여 emacs를 종료하십시오.

변경된 파일 저장

이제, 위의 시련을 겪은 후에 한 단계를 더 수행하면 변경된 파일이 저장됩니다.

emacs 버전 22 이상을 사용하는 경우 ibuffer를 호출하여 버퍼 나열 모드로 이동 한 다음, [* u]를 입력하여 저장되지 않은 모든 파일을 표시 한 다음 S를 입력하여 모두 저장하십시오. (그것은 교대입니다)

emacs 버전 21을 사용하는 경우 다음을 수행 할 수 있습니다. list-buffers를 호출 한 다음 커서를 저장하려는 파일로 이동하고 s를 입력하십시오. 나중에 저장 조치를 위해 파일을 표시합니다. 표시를 해제하려면 u를 입력하십시오. 완료되면 x를 입력하여 저장하도록 표시된 모든 파일의 저장을 실행하십시오. (emacs에서는 열린 파일을 "버퍼"라고합니다. 다른 사항은 무시하십시오.)

위의 옵션 대신, Save-some-buffers [Ctrl + xs]를 호출 할 수도 있습니다. 그러면 emacs는 저장되지 않은 각 파일을 표시하고 저장 여부를 묻습니다.

참고 : emacs의 정규 표현식은 Perl 또는 Python과 동일하지 않지만 비슷합니다. 요약 및 일반적인 패턴은 Emacs Regex를 참조하십시오.


2
이 답변은 내가 희망하는 가장 많이 투표 된 답변보다 초보자에게 친숙하게 만들어야합니다. 링크 대신에 모든 것을 넣도록 동기를 부여해 주셔서 감사합니다.
Prashant Sharma

답은 source :로 시작합니다. 복사 붙여 넣기의 근거는 다음과 같습니다. 때로는 블로그에 대한 외부 링크가 오래되어 응답이 쓸모 없게됩니다. 따라서 위키 메타에서 제안한대로. 나는 모든 것을 복사하기로 결정했습니다.
Prashant Sharma

5

dired를 사용하여 딥 디렉토리 트리를 되풀이하는 것은이 작업에서 약간 느려질 것입니다. tags-query-replace 사용을 고려할 수 있습니다 . 이것은 tags 테이블을 만들기 위해 쉘을 만드는 것을 의미하지만 어쨌든 유용하며 빠릅니다.


14,000 개가 넘는 파일이있는 디렉토리에서 시도했습니다. Emacs에서 팝업하는 데 몇 초가 걸렸습니다. 따라서 더 이상 느려지지 않습니다.
Berend de Boer

3

열린 버퍼의 경우 이것이 내가하는 일입니다.

(defun px-query-replace-in-open-buffers (arg1 arg2)
  "query-replace in all open files"
  (interactive "sRegexp:\nsReplace with:")
  (mapcar
   (lambda (x)
     (find-file x)
     (save-excursion
       (goto-char (point-min))
       (query-replace-regexp arg1 arg2)))
   (delq
    nil
    (mapcar
     (lambda (x)
       (buffer-file-name x))
     (buffer-list)))))

3

M-X Dired, 및 t를 사용하여 모든 파일을 표시하고 모든 파일에서 Q텍스트를 바꾸십시오. iquery-replace 전에 명령 을 사용하여 서브 디렉토리를 펼칠 수 있습니다 . 내가 추가하고있는 주요 정보는 i 명령에 접두어 (control-u)를 주면 arg를 묻는 프롬프트를 표시하고 -R 인수는 모든 subdirs 것을 dired버퍼 로 재귀 적으로 확장한다는 것 입니다. 이제 전체 디렉토리의 모든 파일을 쿼리 검색 할 수 있습니다.


2

또 다른 옵션은 차가워 요 검색 을 사용하는 것 입니다. 이것은 검색 적중에 대한 미니 버퍼 입력 완료를 사용하는 다른 종류의 증분 검색입니다. 현재 입력을 수정하면 일치하는 적중 세트가 버퍼에서 업데이트됩니다 *Completions*.

미니 버퍼 패턴 (예 : 정규 표현식) 일치를 사용하여 선택할 수있는 파일, 버퍼 또는 책갈피 된 위치 수를 얼마든지 검색 할 수 있습니다.

검색 조회를 방문하면 필요시 전체 적중 또는 현재 미니 버퍼 입력과 일치하는 일부만 교체 할 수 있습니다 . 주문형 교체는 각 검색 조회수에 대해 차례로 쿼리하지 않음을 의미합니다. 원하는 순서대로 원하는 조회수에 직접 액세스 할 수 있습니다. 이 방법은 교체 횟수가 제한되어있는 경우 쿼리 교체보다 효과적 일 수 있습니다 y/n. 철저한 프롬프트 를 건너 뜁니다 .

검색은 사용자가 정의한 검색 컨텍스트 를 초과 합니다. 대상 파일의 모든 텍스트를 검색하는 것으로 제한되지 않습니다 (예 : 주석 또는 특정 종류의 프로그램 섹션을 건너 뛸 수 있음). 검색 컨텍스트의 간단한 예는에서와 같이 grep한 줄이지 만 컨텍스트는 원하는 패턴 일치 텍스트 블록 일 수 있습니다. 일반적으로 정규 표현식을 사용하여 검색 컨텍스트를 정의하지만 대신 함수를 사용할 수 있습니다. 사용자 고유의 정의 외에도 텍스트 속성 또는 오버레이 속성, 시점 별 항목 등 다양한 컨텍스트에 대한 미리 정의 된 차가움 검색 명령이 있습니다.

당신은 또한 종류의 쉽게 액세스 / 탐색을위한 다양한 정렬 순서에 검색 안타.


2

find-name-dired 괜찮습니다.

  • 모든 파일은 동일한 단일 정규식과 일치합니다.
  • find-dired이와 관련하여 더 유연하지만 일반적인 규칙을 사용하기 위해 만들어졌습니다 (임의로 복잡 할 수 있더라도). 물론 find고유 한 복잡한 언어가 있습니다.
  • 그런 다음 이름이 find(-name)-dired버퍼에 수집 된 파일 중 일부에 대해서만 작업하려는 경우 해당 파일을 표시하거나 작업하지 않을 파일의 행을 삭제 / 생략해야합니다.

대안은 (a) 표시된 파일 및 (b) 표시된 서브 디렉토리의 모든 표시된 파일 (또는없는 경우 모든 파일)에 대해 반복적으로 발견되는 Dired + 명령 을 사용하는 것입니다 . 이것은 파일 선택에 대한 일반 성과 쉬운 제어를 제공합니다. 이러한 "여기 및 아래"명령은 모두 Dired 모드 에서 접두사 키 에 있습니다.M-+

예를 들어 --- query-replace M-+ Q와 동일 Q하지만 대상 파일은 모두 현재 디렉토리와 표시된 하위 디렉토리, 아래로, 아래로, 아래로 표시된 파일입니다.

예, 여기 아래 명령을 사용하는 것의 대안은 모든 하위 디렉토리와 해당 하위 디렉토리를 재귀 적 으로 삽입 한 다음과 같은 최상위 명령을 사용하는 것 Q입니다. 그러나 삽입 된 하위 디렉토리를 신경 쓰지 않는 것이 종종 편리 할 수 ​​있습니다.

그리고 그렇게하기 위해서는 어쨌든 그러한 모든 하위 디렉토리를 재귀 적 으로 삽입 하는 빠른 방법이 필요합니다 . 여기에, 너무 Dired +는 도움이 될 수 있습니다. M-+ M-i표시된 모든 하위 디렉토리와 자체 표시된 하위 디렉토리를 재귀 적으로 삽입합니다. 즉, M-iDired +에 표시된 하위 디렉토리를 삽입하는 것과 비슷 하지만 하위 디렉토리에서 재귀 적으로 작동합니다.

(이러한 "여기 아래" Dired + 명령은 메뉴 다중 > 여기 및 아래에 표시 됩니다.)

Emacs 파일 세트 에서 Dired 작업을 수행 할 수도 있습니다.이 파일 세트는 어디서나 저장된 파일 이름 세트입니다. 고드름 을 사용 하면 파일 세트 또는 다른 유형의 저장된 파일 목록에있는 파일에 대해서만 Dired 버퍼를 열 수 있습니다.

를 사용하여 생성 한 버퍼를 포함하여 Dired 버퍼를 북마크 할 수도 있습니다 find(-name)-dired. 이렇게하면 나중에 해당 세트 (예 : 프로젝트 세트)로 빠르게 돌아갈 수 있습니다. 그리고 Bookmark + 를 사용 하는 경우 Dired 버퍼 레코드에 책갈피를 지정하면 (a) ls스위치, (b) 표시되는 파일, (c) 삽입 된 하위 디렉토리 및 (d) 숨겨진 (하위) 디렉토리가 기록됩니다. 북마크로 "점프"하면 모든 내용이 복원됩니다. Bookmark + 를 사용하면 Dired 버퍼의 전체 트리를 책갈피로 지정할 수 있습니다. 책갈피로 이동하면 트리의 모든 버퍼가 복원됩니다.


누구든지 : 왜이 ​​답변을 하향 조정했는지 설명해 주시겠습니까?
Drew

1

아직 언급되지 않은 훌륭한 도구, 즉 Helm 을 제안하고 싶습니다 .

완료, 검색 등 많은 표준 Emacs 작업을 대체합니다. 특히, helm-find-files선택한 여러 파일 내에서 정규식을 포함하여 쿼리 바꾸기를 수행 할 수 있습니다.

그냥 개방 helm-find-files과 관련 파일을 표시 M-SPC하고 사용 F6또는 F7대체 쿼리를 실행하거나 선택한 파일에 정규 표현식 대체 쿼리합니다.


helm-find-files대신 정규 표현식으로 표시 할 수 있습니까 M-SPC?
Nordlöw

-2

Emacs는 아니지만 xxdiff는 xx-rename이라는 도구를 제공합니다.이 도구는 대화식 프롬프트, 수정 된 모든 파일의 백업 저장 및 짧은 생성을 통해 한 번에 여러 문자열 (예 : From에서 FROM TO로)을 수행합니다. 컨텍스트로 작성된 변경 사항 로그. 그것이 큰 / 글로벌 이름 바꾸기를 할 때 사용하는 경향이 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.