Why does this awk command not play as well with find as sed does

awkfindsed

I'm creating a Bash shell script to do some file manipulation on some HTML files.

Among the many actions I do, I have this sed command which works great:

find $DIR -type f -name '*.html' -exec sed -i 's/.*<script type="text\/javascript" charset="utf-8" src="file.js"><\/script>.*/<script type="text\/javascript" charset="utf-8" src="file2.js"><\/script>/g' {} \;

It looks through every HTML file in the directory in question, and replaces one line of text.

I wanted to do something similar where I replace multiple lines between two HTML coments.

So I want to take this:

<!-- STARTREPLACE1 -->
Blah
Blah
Blah
<!-- ENDREPLACE1 -->

And change it to:

<!-- STARTREPLACE1 -->
A whole new world!
<!-- ENDREPLACE1 -->

I found this awk command which seems to work when I run it on one file:

awk '/<!-- STARTREPLACE1 -->/{p=1;print;print "A whole new world!"}/<!-- ENDREPLACE1 -->/{p=0}!p' justonefile.html

So I thought I could do the same find function I use with sed and apply that method here in order to run this awk command on every HTML file in the directory:

find $DIR -type f -name '*.html' -exec awk '/<!-- STARTREPLACE1 -->/{p=1;print;print "A whole new world!"}/<!-- ENDREPLACE1 -->/{p=0}!p'

But when I run it, it says:

find: `-exec' no such parameter

Is there a way I can get my awk command to run on all the HTML files?

Bonus question: Can I also remove the two tags around the text I want to replace? So <!-- STARTREPLACE1 --> and <!-- ENDREPLACE1 --> are removed and I only end up with:

A whole new world!

Best Answer

First of all, you need to end the -exec action with {} \;.

Second, awk do not modify the file in place as sed do (with the -i option), so you should send the output to a temporary file, then move this to the original file.

Create a script (say we call it replace) with the following content:

#!/bin/sh
tfile=$(mktemp)
awk '/<!-- STARTREPLACE1 -->/{p=1;print;print "A whole new world!"} 
     /<!-- ENDREPLACE1 -->/  {p=0}' "$1" >"$tfile" && \
  mv "$tfile" "$1"

give it executable permissions

chmod +x ./replace

then run

find "$DIR" -type f -iname '*.html' -exec ./replace {} \;
Related Question