我运行以下命令来替换当前工作目录中所有文件中使用的术语:
$ find . -type f -print0 | xargs -0 sed -i'.bup' -e's/Ms. Johnson/Mrs. Melbin/g'
这执行了单词替换,但它也创建了.bup
从未包含该字符串的文件的文件Ms. Johnson
。
如何执行替换而不创建所有这些不必要的备份?
答案1
Find 有一个-exec
执行任意命令的运算符。更好的是,-exec
是一个测试,因此您可以将多个-exec
命令链接在一起,如果较早的命令失败,则后面的命令将不会被执行。该字符串{}
将替换为当前文件名,并;
标记命令的结束。您应该引用两者以避免 shell 干扰。
所以:
find . -type f \
-exec grep -q 'Ms. Johnson' '{}' \; \
-exec sed -i'.bup' -e's/Ms. Johnson/Mrs. Melbin/g' '{}' \;
答案2
您可以检查文件的内容以确保在sed
对其进行操作时会发生替换:
find . \
-type f \
-exec grep -q 'Ms. Johnson' {} \; \
-print0 |
xargs -0 sed -i'.bup' -e's/Ms. Johnson/Mrs. Melbin/g'
如果你想真正做到聪明,你可以find
完全放弃使用:
grep -Z -l -r 'Ms. Johnson' |
xargs -0 sed -i'.bup' -e's/Ms. Johnson/Mrs. Melbin/g'
答案3
我查看了手册页,没有看到任何直接通过 执行此操作的方法sed
,正如我确信您在询问之前所做的那样。我看到有几种使用 grep 解决这个问题的方法,但我认为最简单的是:
grep -rlZ "Ms. Johnson" . | xargs -0 sed -i'.bup' -e's/Ms. Johnson/Mrs. Melbin/g'
-r
递归
-l
打印文件名仅以
-Z
空结尾的名称
答案4
似乎您需要首先构建与您的搜索词匹配的文件列表。
search="test"
for match in $(find -type f -exec grep -l $search "{}" \;)
do sed -i'.bup' -e "/$search/ s/$search/Mrs. Melbin/g" "$match"
done