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

时间:2009-10-18 15:32:14

标签: sed find grep replace

只使用grep和sed,如何替换所有出现的:

a.example.com

b.example.com

/home/user/目录树下的文本文件中递归查找并替换子目录中所有文件中的所有匹配项。

9 个答案:

答案 0 :(得分:67)

试试这个:

find /home/user/ -type f | xargs sed -i  's/a.example.com/b.example.com/g'

如果您想忽略点目录

find . \( ! -regex '.*/\..*' \) -type f | xargs sed -i 's/a.example.com/b.example.com/g'

答案 1 :(得分:26)

试试这个:

SELECT pet, hobby, SUM(weight)
FROM weights JOIN pets on weights.person_id=pets.person_ID
JOIN hobbies on weights.person_id=hobbies.person_id
GROUP BY pet, hobby
UNION
SELECT pet, NULL, SUM(weight)
FROM weights JOIN pets on weights.person_id=pets.person_ID
GROUP BY pet
UNION
SELECT NULL, hobby, SUM(weight)
FROM weights JOIN hobbies on weights.person_id=hobbies.person_id
GROUP BY hobby
UNION
SELECT SUM(weight)
FROM weights

grep -rl 'SearchString' ./ | xargs sed -i 's/REPLACESTRING/WITHTHIS/g' 将递归搜索目录grep -rl中的SEARCHSTRING,并使用./替换字符串。

例如:

使用sed中的TOM搜索字符串替换名称JERRY SWATKATS

CARTOONNETWORK

这将在grep -rl 'SWATKATS' CARTOONNETWORK/ | xargs sed -i 's/TOM/JERRY/g' 下的所有文件和子目录中将TOM替换为JERRY,只要它找到字符串CARTOONNETWORK

答案 2 :(得分:4)

我知道这是一个非常古老的问题,但是......

    当问题明确findxargs时,
  1. @ vehomzzz的答案会使用grepsed

  2. @EmployedRussian和@BrooksMoses试图说它是awksed的副本,但它不是 - 再次,问题明确地说grepsed

  3. 所以这是我的解决方案,假设你使用Bash作为你的shell:

    OLDIFS=$IFS
    IFS=$'\n'
    for f in `grep -rl a.example.com .` # Use -irl instead of -rl for case insensitive search
    do
        sed -i 's/a\.example\.com/b.example.com/g' $f # Use /gi instead of /g for case insensitive search
    done
    IFS=$OLDIFS
    

    如果您使用的是其他shell,例如Unix SHell,请告诉我,我会尝试找到语法调整。

    P.S。:这是一个单行:

    OLDIFS=$IFS;IFS=$'\n';for f in `grep -rl a.example.com .`;do sed -i 's/a\.example\.com/b.example.com/g' $f;done;IFS=$OLDIFS
    

    来源:

答案 3 :(得分:2)

对我来说,下一个命令是:

find /path/to/dir -name "file.txt" | xargs sed -i 's/string_to_replace/new_string/g'

如果string包含斜杠'path / to / dir',则可以将其替换为另一个要分隔的字符,例如'@'而不是'/'。

例如:'s@string/to/replace@new/string@g'

答案 4 :(得分:1)

尝试此命令:

/home/user/ directory - find ./ -type f \
-exec sed -i -e 's/a.example.com/b.example.com/g' {} \;

答案 5 :(得分:1)

它比那简单得多。

for i in `find *` ; do sed -i -- 's/search string/target string/g' $i;

完成

find i =>将把文件夹和子文件夹中的所有文件引入SED。

sed -i =>将在文件中替换相关字符串(如果存在)。

答案 6 :(得分:1)

我们可以尝试使用更强大的 ripgrep 作为

rg "BYE_BYE_TEXT" ./ --files-with-matches | xargs sed -i "s/BYE_BYE_TEXT/WELCOME_TEXT/g"

因为 ripgrep 擅长查找而 sed 擅长替换。

答案 7 :(得分:0)

下面的命令将以递归方式搜索其名称与搜索模式匹配的所有文件,并将替换字符串:

find /path/to/searchdir/ -name "serachpatter" -type f | xargs sed -i 's/stringone/StrIngTwo/g'

此外,如果您想限制递归的深度,您也可以设置限制:

find /path/to/searchdir/ -name "serachpatter" -type f -maxdepth 4 -mindepth 2 | xargs sed -i 's/stringone/StrIngTwo/g'

答案 8 :(得分:0)

在macOS上,没有答案对我有用。我发现这是由于与GNU相比sed在macOS和其他BSD系统上的工作方式不同。

尤其是BSD sed takes the -i option but requires a suffix for the backup (but an empty suffix is permitted)

来自this answer

grep版本。

grep -rl 'foo' ./ | LC_ALL=C xargs sed -i '' 's/foo/bar/g'
来自this answer

find版本。

find . \( ! -regex '.*/\..*' \) -type f | LC_ALL=C xargs sed -i '' 's/foo/bar/g'

如果您在Git存储库中,请不要忽略正则表达式以忽略.文件夹。我意识到这很困难!

LC_ALL=C选项用于avoid getting sed: RE error: illegal byte sequence if sed finds a byte sequence that is not a valid UTF-8 character。这是BSD和GNU之间的另一个区别。根据您要处理的文件类型,您可能不需要它。

由于某些我不清楚的原因,发现grep版本比find版本更多,这就是为什么我建议使用grep的原因。