在Emacs中替换目录/子目录中所有文件的文本?

4

我需要在一个目录中的所有文件中替换某个特定字符串,这个目录下还有子目录,其中的文件也需要被替换。在Emacs中是否有实现这一需求的方法?


2
我建议考虑使用递归的 grep 查找所有需要更改的位置,然后使用 wgrep 将它们全部更改。在 wgrep 中,您可以使用 M-x replace-string 或使用 multiple-cursors - lawlist
helm-ag非常适合这个。 - Chris Stryczynski
3个回答

6

我通常采用@lawlist建议的方法。以下是逐步说明:

  1. 从Melpa或其他途径安装wgrep,如果您使用The Silver Searcher,则还推荐wgrep-agag

  2. 使用M-x rgrep(或M-x ag)搜索文件并获取潜在更改行的列表。

  3. *grep*缓冲区中,运行M-x wgrep-change-to-wgrep-mode。我将其绑定到grep-mode-map中的C-x C-q

  4. 使用query-replace-regexpC-M-%)或在*grep*缓冲区中进行任何其他编辑。

  5. 使用C-x C-s保存*grep*缓冲区。使用C-c C-k取消。更改仅存在于*grep*缓冲区中,直到您保存它。您可以多次重新启用wgrep模式。

  6. 如果保存了*grep*缓冲区,则grep搜索中的所有文件现在都具有修改后的打开缓冲区。使用C-x s将它们全部保存到磁盘。


5
交互方式是获取所有文件的目录列表,标记您感兴趣的文件(可能是全部文件),然后在它们所有文件上运行查询替换。做法如下:
1. 在你的目录上使用`find-dired`,参数为`-type f`来获取文件而不是目录(您可以用类似`-type f -name "*.txt"`的方法进一步筛选类型)。这将使您获得包含所有文件的dired列表。
2. 标记所有文件(按下T键)或标记包含特定文本的文件(使用% g)。
3. 现在在所有标记文件上运行`query-replace-regexp`,并按下S-Q(大写Q)。
如果查询替换成功,您可以通过键入!继续加快速度而无需询问。

4

普通的emacs:

  • 调用dired来列出目录中的文件,或者如果需要所有子目录,则调用find-dired。
  • 标记您想要的文件。您可以通过键入【% m】按正则表达式进行标记。
  • 键入Q来调用dired-do-query-replace-regexp。
  • 键入您的查找正则表达式和替换字符串。〔➤参见常见的elisp正则表达式模式〕
  • 对于每个匹配项,键入y以替换,n以跳过。键入【Ctrl+g】以中止整个操作。
  • 键入!以替换当前文件中的所有匹配项而不询问,键入N以跳过当前文件剩余部分的所有可能替换。(仅适用于emacs 23)
  • 要在所有文件上执行替换而无需进一步询问,请键入Y。(仅适用于emacs 23)
  • 调用ibuffer来列出所有打开的文件。
  • 键入【* u】来标记所有未保存的文件,键入S来保存所有标记的文件,键入D来关闭它们所有。

更多细节请参见 http://ergoemacs.org/emacs/find_replace_inter.html


或者,我编写了一个专门用于此目的的包。请参见: http://ergoemacs.org/emacs/elisp-xah-find-text.html 经过5年的尝试和错误后,我终于找到了它。

它完全使用emacs lisp实现,不依赖于shell find/grep/sed等。因此在Windows上可以很好地工作。此外,它一次完成查找/替换,并带有彩色的报告。所以它很快,让您可以快速检查结果以防万一。备份是可选的。


基本上,这需要使用“find”实用程序列出所有匹配的文件,然后替换每个出现的位置,对吧?但在Windows中该怎么做呢? - Michael Wei
@Michael Wei 它是用 elisp 实现的,因此不依赖于 shell 工具。 - Xah Lee
纯净的 Emacs 方法在 Emacs 30 上仍然有效。 - Alexander Gogl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接