我需要对文件夹(及其子文件夹)中的所有文件进行正则表达式查找和替换。 linux shell命令会做什么?
例如,我想在所有文件上运行它,并使用新的替换文本覆盖旧文件。
sed 's/old text/new text/g'
答案 0 :(得分:108)
仅使用sed无法做到这一点。您至少需要使用find实用程序:
find . -type f -exec sed -i.bak "s/foo/bar/g" {} \;
此命令将为每个更改的文件创建一个.bak
文件。
注意:
-i
命令的sed
参数是GNU扩展名,因此,如果您使用BSD的sed
运行此命令,则需要将输出重定向到新文件,然后重命名。find
实用程序未在旧UNIX框中实现-exec
参数,因此,您需要使用| xargs
代替。答案 1 :(得分:35)
我更喜欢使用find | xargs cmd
而不是find -exec
,因为它更容易记住。
此示例全局替换" foo"用" bar"在当前目录或以下的.txt文件中:
find . -type f -name "*.txt" -print0 | xargs -0 sed -i "s/foo/bar/g"
如果您的文件名不包含空格等时髦字符,则可以省略-print0
和-0
选项。
答案 2 :(得分:6)
为了便于携带,我不依赖于特定于linux或BSD的sed功能。相反,我使用了Kernighan的overwrite
脚本和Pike在Unix编程环境中的书。
然后命令
find /the/folder -type f -exec overwrite '{}' sed 's/old/new/g' {} ';'
overwrite
脚本(我在整个地方使用)是
#!/bin/sh
# overwrite: copy standard input to output after EOF
# (final version)
# set -x
case $# in
0|1) echo 'Usage: overwrite file cmd [args]' 1>&2; exit 2
esac
file=$1; shift
new=/tmp/$$.new; old=/tmp/$$.old
trap 'rm -f $new; exit 1' 1 2 15 # clean up files
if "$@" >$new # collect input
then
cp $file $old # save original file
trap 'trap "" 1 2 15; cp $old $file # ignore signals
rm -f $new $old; exit 1' 1 2 15 # during restore
cp $new $file
else
echo "overwrite: $1 failed, $file unchanged" 1>&2
exit 1
fi
rm -f $new $old
这个想法是只有在命令成功时它才会覆盖文件。适用于find
以及您不想使用的地方
sed 's/old/new/g' file > file # THIS CODE DOES NOT WORK
因为shell在sed
可以读取之前截断文件。
答案 3 :(得分:1)
我建议(备份文件后):
find /the/folder -type f -exec sed -ibak 's/old/new/g' {} ';'
答案 4 :(得分:1)
for i in $(ls);do sed -i 's/old_text/new_text/g' $i;done
答案 5 :(得分:0)
示例:将/ app / config /文件夹及其子文件夹下的所有ini文件的{AutoStart}替换为1:
sed 's/{AutoStart}/1/g' /app/config/**/*.ini
答案 6 :(得分:0)
这对我有用(在Mac终端上,在Linux上您不需要'' -e
):
sed -i '' -e 's/old text/new text/g' `grep 'old text' -rl *`
命令grep 'old text' -rl *
列出存在“旧文本”的工作目录(和子目录)中的所有文件。然后将其传递给sed。
答案 7 :(得分:-3)
可能想尝试my mass search/replace Perl script。与链式效用解决方案相比具有一些优势(比如不必处理多级shell元字符解释)。
答案 8 :(得分:-3)
如果文件夹中的文件名有一些常规名称(如file1,file2 ......),我已经用于循环。
for i in {1..10000..100}; do sed 'old\new\g' 'file'$i.xml > 'cfile'$i.xml; done