我喜欢使用以下命令在 bash 中跨多个文件进行查找/替换:
find -wholename "*.txt" -print | xargs sed -i 's/foo/bar/g'
但是,上面的命令会默默地处理所有内容,有时我希望上面的命令打印它所做的所有更改,以便仔细检查我是否正确地完成了所有操作。我能知道我应该如何改进上述命令以允许它转储此类信息吗?我尝试了命令中的-v
参数,xargs
但它给了我invalid option
错误。
您可以执行以下操作:
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
为了查看差异,您可以将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