我需要在当前目录中从名称file_ *开始替换所有文件中的字符串。
例如:/
cat file_1
test1
test2
test3
cat file_2
test4
test2
test3
我想从当前目录中的两个文件中用test2
替换test100
。
以下命令查找并替换字符串,但不列出已修改的文件。
find . -name '*file_*'|xargs sed -i 's/test2/test100/g'
有人可以帮我解决这个问题吗?我想显示已修改的所有文件名。
谢谢!
答案 0 :(得分:4)
仅列出实际已修改的文件(假设为Linux):
find . -name '*file_*' -exec sh -c \
'md5Before=$(md5sum "{}");
sed -i "s/test2/test100/g" "{}";
[ "$(md5sum "{}")" != "$md5Before" ] && echo "{}"' \;
在OSX上,将md5sum
替换为md5
并使用-i ""
而不只是-i
。
请注意,在这种情况下,比较上次修改的时间戳(Linux上的stat -c %Y
,OSX上的stat -f %m
)不是一个选项,因为sed -i
将重写所有文件,即使他们的内容未被修改。
更新:@Jonathan Leffler建议采用更简洁优雅的替代方案:
find . -name '*file_*' -exec sh -c \
'grep -l "test2" "{}" && sed -i "s/test2/test100/g" "{}";' \;
grep -l
列出(输出)输入文件名,但仅在找到匹配项时(并在找到第一次匹配后立即退出)sed -i
命令(感谢&&
)除了更短(并且更可能更快)之外,增加的优势是不会重写所有文件 - 只有那些实际需要它的文件。
(唯一的缺点是搜索词是重复的,但您可以将其分配给shell变量并将其拼接到两个位置的sed
程序中;如果搜索词是复杂的正则表达式,那么事情可能会变得棘手,因为正则表达式的支持因公用事业而异。