在目录和子目录中查找并替换为 sed

Posted

技术标签:

【中文标题】在目录和子目录中查找并替换为 sed【英文标题】:Find and replace with sed in directory and sub directories 【发布时间】:2011-10-09 04:38:39 【问题描述】:

我运行此命令在我站点根目录的所有文件中查找所有出现的“apple”并将其替换为“orange”:

find ./ -exec sed -i 's/apple/orange/g'  \;

但它不经过子目录。

这个命令有什么问题?

这是find ./的一些输出:

./index.php
./header.php
./fpd
./fpd/font
./fpd/font/desktop.ini
./fpd/font/courier.php
./fpd/font/symbol.php

【问题讨论】:

您能运行find ./ 并发布一些示例输出吗?和目录结构请。编辑:谢谢! 嗯,你的发现是正确的,适用于我的子目录。 你怎么知道它不处理子目录? 因为它给出了以下错误: sed:无法编辑 ./fpd:不是常规文件 sed:无法编辑 ./fpd/font:不是常规文件 sed:无法编辑./fpd/font/makefont: 不是规则 哦...我用 grep 搜索苹果,但什么也没找到。它们都被替换了。 ;) 谢谢 。你睁开了我的眼睛!!! 【参考方案1】:

您的find 应该看起来像这样,以避免将目录名称发送到sed

find ./ -type f -exec sed -i -e 's/apple/orange/g'  \;

【讨论】:

您可能需要将sed -i 's/apple/orange/g' 更改为sed -i '' 's/apple/orange/g' 才能完成这项工作。 -i 接受一个参数:用于保存临时文件的扩展名。在 GNU sed 中,-i 和它的参数之间似乎没有空格,但在 BSD sed 中有……所以 BSD -i '' 's/foo/bar/' 等同于 GNU -i 's/foo/bar/ 实际上添加-e 不适用于Mac OS。 touch a b c d e 后跟上面的命令会生成一个目录列表,如下所示:a a-e b b-e c c-e d d-e e e-e 对于 Mac OS,这个答案是 ***.com/questions/19242275/… RE error: illegal byte sequence 对于 fish shell 用户,一定要引用空括号'',因为如果没有引用,fish 会自动扩展空括号。【参考方案2】:

由于也有 macOS 人在阅读这篇文章(和我一样),因此以下代码对我有用(在 10.14 上)

egrep -rl '<pattern>' <dir> | xargs -I@ sed -i '' 's/<arg1>/<arg2>/g' @

使用 -i-e 的所有其他答案在 macOS 上均无效。

Source

【讨论】:

在 Mac 上,接受的答案确实有效 [种类] - 但它使用 -e 吐出“重复”文件,需要将其删除/通过管道传输到另一个命令(逐字使用)。这种方法虽然更好,但仍然对我有用(在 11.2.3 上)【参考方案3】:

我认为我们可以用一行简单的命令来做到这一点

for i in `grep -rl eth0 . 2> /dev/null`; do sed -i ‘s/eth0/eth1/’ $i; done

请参阅此page。

【讨论】:

【参考方案4】:
grep -e apple your_site_root/**/*.* -s -l | xargs sed -i "" "s|apple|orage|"

【讨论】:

【参考方案5】:

在 linux 操作系统中:

sed -i 's/textSerch/textReplace/g' namefile

如果“sed”不起作用,请尝试:

perl -i -pe 's/textSerch/textReplace/g' namefile

【讨论】:

他要查找子目录中包含该字符串的所有文件并替换,而不仅仅是单个文件【参考方案6】:

对于较大的 s&r 任务,使用 grep 和 xargs 会更好更快,例如;

grep -rl 'apples' /dir_to_search_under | xargs sed -i 's/apples/oranges/g'

【讨论】:

感谢您的回答,非常有帮助!如果在 git 存储库中,使用 git grep -l 'apples' | xargs sed -i 's/apples/oranges/g' 会更快 如果在macos上,使用xargs sed -i '' 's/apples/oranges/g'【参考方案7】:

这对我有用:

find ./ -type f -exec sed -i '' 's#NEEDLE#REPLACEMENT#' *.php  \;

【讨论】:

原始问题不限于 *.php 文件,还有一个 .ini 文件 未引用的*.php 确实不正确;您很幸运,它没有在起始目录中展开,因为那里没有任何匹配的文件。 文件名限制可以通过find命令上的-name *.php获得。

以上是关于在目录和子目录中查找并替换为 sed的主要内容,如果未能解决你的问题,请参考以下文章

如何在目录树中递归查找和替换所有出现的字符串? [复制]

关于find与sed命令的几个使用

使用Vim在所有文件中进行交互式查找和替换,包括子目录中的文件

企业面试题-find结合sed查找替换

Linux 查找当前目录下所有包含指定内容的文件

正则介绍 sed