这是我当前的代码,我的目标是找到给定目录中的每个文件(递归地)并替换" FIND"用" REPLACEWITH"并覆盖文件。
FIND='ALEX'
REPLACEWITH='<strong>ALEX</strong>'
DIRECTORY='/some/directory/'
find $DIRECTORY -type f -name "*.html" -print0 |
LANG=C xargs -0 sed -i "s|$FIND|$REPLACEWITH|g"
我得到的错误是:
sed: 1: "/some/directory ...": command a expects \ followed by text
答案 0 :(得分:2)
如BashFAQ #21中所述,您可以使用perl
执行搜索和替换操作,而不会将数据视为代码:
in="$FIND" out="$REPLACEWITH" find "$DIRECTORY" -type f -name '*.html' \
-exec perl -pi -e 's/\Q$ENV{"in"}/$ENV{"out"}/g' '{}' +
如果您只想包含与FIND字符串匹配的文件,可以告诉find
仅将grep
标记的文件传递到perl
:
in="$FIND" out="$REPLACEWITH" find "$DIRECTORY" -type f -name '*.html' \
-exec grep -F -q -e "$FIND" '{}' ';' \
-exec perl -pi -e 's/\Q$ENV{"in"}/$ENV{"out"}/g' '{}' +
由于grep
用于评估单个文件,因此必须对每个文件使用一次grep
调用,以便可以基于每个文件评估其退出状态。因此,使用效率较低的-exec ... {} ';'
动作。对于perl
,可以在一个命令上放置多个文件,因此使用-exec ... {} +
。
请注意fgrep
是面向行的;如果您的FIND
字符串包含多行,则包含这些行中任意一行的文件将传递到perl
以进行替换。
答案 1 :(得分:1)
您可以find
直接调用sed
,但我认为您文件的所有修改时间都会受到影响(这可能很重要或不重要):
find $DIRECTORY -type f -name "*.html" -exec sed -i "s|$FIND|$REPLACEWITH|g" '{}' ';'