我需要替换一个文件夹中的许多文件中的字符串,只有ssh访问服务器。我该怎么做呢?


当前回答

multiedit命令脚本

multiedit [-n PATTERN] OLDSTRING NEWSTRING

根据Kaspar的回答,我编写了一个bash脚本来接受命令行参数,并有选择地限制与模式匹配的文件名。保存在$PATH中并使其可执行,然后使用上面的命令。

剧本如下:

#!/bin/bash
_help="\n
Replace OLDSTRING with NEWSTRING recursively starting from current directory\n
multiedit [-n PATTERN] OLDSTRING NEWSTRING\n

[-n PATTERN] option limits to filenames matching PATTERN\n
Note: backslash escape special characters\n
Note: enclose STRINGS with spaces in double quotes\n
Example to limit the edit to python files:\n
multiedit -n \*.py \"OLD STRING\" NEWSTRING\n"

# ensure correct number of arguments, otherwise display help...
if [ $# -lt 2 ] || [ $# -gt 4 ]; then echo -e $_help ; exit ; fi
if [ $1 == "-n" ]; then  # if -n option is given:
        # replace OLDSTRING with NEWSTRING recursively in files matching PATTERN
        find ./ -type f -name "$2" -exec sed -i "s/$3/$4/g" {} \;
else
        # replace OLDSTRING with NEWSTRING recursively in all files
        find ./ -type f -exec sed -i "s/$1/$2/" {} \;
fi

其他回答

当使用-i开关调用时,流编辑器确实会“inplace”修改多个文件,该开关以备份文件结尾作为参数。所以

sed -i.bak 's/foo/bar/g' *

在此文件夹中的所有文件中,将foo替换为bar,但不会下降到子文件夹中。但是,这将为目录中的每个文件生成一个新的.bak文件。 要递归地为该目录及其所有子目录中的所有文件执行此操作,您需要一个助手(如find)来遍历目录树。

find ./ -print0 | xargs -0 sed -i.bak 's/foo/bar/g' *

Find允许您进一步限制要修改的文件,通过指定进一步的参数,如Find ./ -name '*.php' -或name '*.html' -print0(如有必要)。


注意:GNU sed不需要文件结尾,sed -i 's/foo/bar/g' *也可以;FreeBSD sed要求扩展,但允许中间有一个空格,因此sed -i .bak s/foo/bar/g *可以工作。

使用ack命令会快得多,像这样:

ack '25 Essex' -l | xargs sed -i 's/The\ fox \jump/abc 321/g'

如果你在搜索结果中有空白。你需要逃离它。

cd /path/to/your/folder
sed -i 's/foo/bar/g' *

出现的“foo”将被替换为“bar”。

在像macOS这样的BSD系统上,你需要提供一个备份扩展名,比如-i '.bak',否则每个manpage都会“冒损坏或部分内容的风险”。

cd /path/to/your/folder
sed -i '.bak' 's/foo/bar/g' *

要替换多个文件中的字符串,您可以使用:

grep -rl string1 somedir/ | xargs sed -i 's/string1/string2/g'

E.g.

grep -rl 'windows' ./ | xargs sed -i 's/windows/linux/g'

源的博客

我给出了一个修复python源代码中常见shebang错误的示例。

您可以尝试grep/sed方法。下面是一个适用于GNU sed并且不会破坏git回购的程序:

$ grep -rli --exclude '*.git*' '#!/usr/bin/python' . | xargs -I {} \
gsed -i '' -e 's/#!\/usr\/bin\/python/#!\/usr\/bin\/env python/' {}

或者你可以使用greptile:)

$ greptile -x .py -l -i -g '#!/usr/bin/env python' -r '#!/usr/bin/python' .

我刚刚测试了第一个脚本,第二个脚本应该也可以工作。小心转义字符,我认为在大多数情况下使用greptile应该更容易。当然,您可以使用sed做许多有趣的事情,为此,最好与xargs一起使用sed。