我如何查找并替换每次出现的:

subdomainA.example.com

具有

subdomainB.example.com

递归地在/home/www/目录树下的每个文本文件中?


当前回答

这是我为OSX和Windows(msys2)找到的最好的全方位解决方案。应该可以使用任何可以获得gnu版本sed的东西。跳过.git目录,这样不会损坏您的校验和。

在mac上,只需先安装coreutils并确保gsed在路径中-

brew install coreutils

然后我将此函数粘贴到zshrc/bashrc->

replace-recursive() {
    hash gsed 2>/dev/null && local SED_CMD="gsed" || SED_CMD="sed"
    find . -type f -name "*.*" -not -path "*/.git/*" -print0 | xargs -0 $SED_CMD -i "s/$1/$2/g"
}

usage: replace-recursive <find> <replace>

其他回答

所有的技巧都差不多,但我喜欢这个:

find <mydir> -type f -exec sed -i 's/<string1>/<string2>/g' {} +

find<mydir>:在目录中查找。-类型f:文件类型:常规文件-exec命令{}+:-exec操作的这个变体在选定的文件上运行指定的命令,但命令行是通过附加结尾处的每个选定文件名;命令的调用总数将大大少于匹配的文件。命令行的构建方式与xargs构建命令行的方式大致相同。只有一个实例`命令中允许使用“{}”。该命令在起始目录中执行。

cd /home/www && find . -type f -print0 |
      xargs -0 perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g'

我只是需要这一点,并对现有示例的速度感到不满意。所以我想出了自己的办法:

cd /var/www && ack-grep -l --print0 subdomainA.example.com | xargs -0 perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g'

Ack-grep在查找相关文件方面非常有效。这个命令轻而易举地替换了约145000个文件,而其他命令耗时太长,我无法等到它们完成。

这是我为OSX和Windows(msys2)找到的最好的全方位解决方案。应该可以使用任何可以获得gnu版本sed的东西。跳过.git目录,这样不会损坏您的校验和。

在mac上,只需先安装coreutils并确保gsed在路径中-

brew install coreutils

然后我将此函数粘贴到zshrc/bashrc->

replace-recursive() {
    hash gsed 2>/dev/null && local SED_CMD="gsed" || SED_CMD="sed"
    find . -type f -name "*.*" -not -path "*/.git/*" -print0 | xargs -0 $SED_CMD -i "s/$1/$2/g"
}

usage: replace-recursive <find> <replace>

这是一个比大多数版本更通用的版本;例如,它不需要查找(而是使用du)。它确实需要xargs,只有在Plan9的某些版本(如9front)中才能找到xargs。

 du -a | awk -F' '  '{ print $2 }' | xargs sed -i -e 's/subdomainA\.example\.com/subdomainB.example.com/g'

如果要添加文件扩展名等筛选器,请使用grep:

 du -a | grep "\.scala$" | awk -F' '  '{ print $2 }' | xargs sed -i -e 's/subdomainA\.example\.com/subdomainB.example.com/g'