使用单行shell命令在所有文件中替换特定文本

42

我有一个被重命名的js文件,我需要在每个php页面中调用它。现在我想使用shell将旧名称替换为新名称。

我正在使用以下代码:

sed -i ’s/old/new/g’ *

但是这会导致以下错误:

sed: -e expression #1, char 1: unknown command:

我该如何进行这个替换?

8个回答

56
sed -i.bak 's/old/new/g' *.php

递归地完成它

find /path -type f -iname '*.php' -exec sed -i.bak 's/old/new/' "{}" +;

@WimPruiksma,我在Mac上使用BSD sed时也遇到了同样的错误,但是使用brew安装的GNU sed(作为gsed)却没有出现这个问题。 - DaCheetah
1
sed -i 不是 POSIX 标准所必需的,因此在 OS X 或 BSD 中没有它,如果我没记错的话。 - Wyatt Ward
注意:我刚刚使用 sed -i''-e'...' 在 FreeBSD 11.3 上替换了文件中的内容,具体方法可以参考 https://dev59.com/-Wcs5IYBdhLWcg3woFbt 中的回答。 - Piohen

33

可能有更为简洁的解决方案,但是这里我们来介绍一下:

for i in *; do sed -i 's/old/new/g' "$i"; done

要注意的是,它只能在当前级别的文件系统上运行,子目录中的文件将不会被修改。此外,您可能想要用*.php替换*,或者进行备份(在-i后面传递一个参数,它将使用给定的扩展名进行备份)。


1
在OSX上,您有BSD sed,并且需要在-i选项中传递文件扩展名以进行备份。请查看此页面:https://dev59.com/Om855IYBdhLWcg3wm1q3 - spectrum
我在许多文件夹中遇到了“sed: couldn't edit includes: not a regular file”的错误。 - Black
我假设它们是FIFO或设备文件,或者是其他不同于常规文件的东西。如果您有非常规文件,则必须使用其他东西而不是glob(例如find -type f ...)。 - K. Norbert

12

这个命令非常简单,不需要使用for或loop,适用于任何数量或嵌套目录。

grep -rl '旧文本' [文件夹名称-可选] | xargs sed -i 's/旧文本/新文本/g'


我在这个递归目录中得到了“没有这样的文件或目录”的错误。 - dman
@dman 可能你是以 [文件夹名称-可选] 的形式运行的,而没有更改它。你可以将其删除,或者只保留单个点而不加引号 grep -rl 'oldText' . | xargs sed -i 's/oldText/newText/g' - user7154703

10

你在sed命令参数周围使用了Unicode撇号(右单引号-U2019),而不是ASCII撇号(0x27)。


9

我知道我真的很晚了,但还是要说:

find . -type f -name "*.php"|xargs sed -i 's/old/new/g'

1
最佳答案在这里。 - VAdaihiep

4
perl -pi -e 's/old/new/g' *.php

在OSX上出现了一个错误 zsh:参数列表太长:perl - james-see

3
为了完整性,提供以上被接受答案的OSX兼容版本(回复@jamescampbell的评论)。
for i in *.php; do sed -i .orig 's/old/new/g' "$i"; done

这个命令会创建.orig备份文件。

-3

试试这个:

ls | grep "php" > files.txt
for file in $(cat files.txt); do
    sed 's/catch/send/g' $file > TMPfile.php && mv TMPfile.php $file
done

1
不知道是否无用,但这是一种非常丑陋的方法,而且使用固定的临时文件名(files.txt、TMPfile.php)会在并发情况下出现问题。 - symcbean

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