0

我喜欢使用以下命令在 bash 中跨多个文件进行查找/替换:

find -wholename "*.txt" -print | xargs sed -i 's/foo/bar/g'

但是,上面的命令会默默地处理所有内容,有时我希望上面的命令打印它所做的所有更改,以便仔细检查我是否正确地完成了所有操作。我能知道我应该如何改进上述命令以允许它转储此类信息吗?我尝试了命令中的-v参数,xargs但它给了我invalid option错误。

4

3 回答 3

1

您可以执行以下操作:

find -wholename "*.txt" | xargs sed -n '/foo/p;s/foo/bar/gp'

这将打印您希望替换的行并在下一行打印替换。

您也可以使用awk和获取文件名:

find -wholename "*.txt" | xargs awk '/foo/{print FILENAME; gsub(/foo/,"bar");print}'

打印整个文件删除print和添加1

find -wholename "*.txt" | xargs awk '/foo/{print FILENAME; gsub(/foo/,"bar")}1'

正则表达式必须根据您的要求进行修改,文件中的更改仅适用于gawk version 4.1

测试:

$ head file*
==> file1 <==
,,"user1","email"
,,"user2","email"
,,"user3","email"
,,"user4","email"

==> file2 <==
,,user2,location2
,,user4,location4
,,user1,location1
,,user3,location3
$ find . -name "file*" -print | xargs awk '/user1/{print FILENAME; gsub(/user1/,"TESTING");print}'
./file1
,,"TESTING","email"
./file2
,,TESTING,location1
 
于 2013-06-26T05:14:15.360 回答
1

为了查看差异,您可以将sed每个输入文件的输出重定向到一个新文件,并将其与原始文件进行比较。

for i in `find -wholename "*.txt"`; do
  sed 's/foo/bar/g' ${i} > ${i}.new;
  diff -u ${i} ${i}.new;
done

如果更改看起来没问题,请将新文件移至其原始名称。

for i in `find -wholename "*.new"` ; do
  mv ${i} ${i/.new};
done
于 2013-06-26T05:17:14.413 回答
1

一切都可以用来完成。只需要一点点修改:

find -path "*.txt" -exec sed -i.bak 's/foo/bar/g' {} +

这会以最大文件数调用+ (注意在 末尾-exec),因此不需要 -i.bak中进行就地编辑,将原始文件重命名为.bak. 因此,如果需要,您可以稍后检查差异。

man find一个可以阅读:

-wholename pattern
      See -path.    This alternative is less portable than -path.
于 2013-06-26T07:44:58.547 回答