Accelerate set of sed commands in files (recursively over full directory) I run this to fix some hard-coded references, replacing occurrences of mywar by clientwar:

find . -type f -exec sed -i "s% '/mywar/% '/clientwar/%g" {} +
find . -type f -exec sed -i "s%,'/mywar/%,'/clientwar/%g" {} +
find . -type f -exec sed -i 's% "/mywar/% "/clientwar/%g' {} +
find . -type f -exec sed -i 's% file="/mywar/% file="/clientwar/%g' {} +
find . -type f -exec sed -i 's%&lt;TAB&gt;href="/mywar/%&lt;TAB&gt;href="/clientwar/%g' {} +
find . -type f -exec sed -i 's% href="/mywar/% href="/clientwar/%g' {} +
find . -type f -exec sed -i 's% name="/mywar/% name="/clientwar/%g' {} +
find . -type f -exec sed -i 's% relativePath="/mywar/% relativePath="/clientwar/%g' {} +
find . -type f -exec sed -i 's% requestUrl.indexOf("/mywar/")% requestUrl.indexOf("/clientwar/")%g' {} +
find . -type f -exec sed -i "s% src='/mywar/% src='/clientwar/%g" {} +
find . -type f -exec sed -i 's%&lt;TAB&gt;src="/mywar/%&lt;TAB&gt;src="/clientwar/%g' {} +
find . -type f -exec sed -i 's% src="/mywar/% src="/clientwar/%g' {} +
find . -type f -exec sed -i "s% url('/mywar/% url('/clientwar/%g" {} +
find . -type f -exec sed -i 's% url("/mywar/% url("/clientwar/%g' {} +
find . -type f -exec sed -i 's% url(/mywar/% url(/clientwar/%g' {} +
find . -type f -exec sed -i 's% url="/mywar/% url="/clientwar/%g' {} +
find . -type f -exec sed -i 's% value="/mywar/% value="/clientwar/%g' {} +
find . -type f -exec sed -i 's% webapps/mywar/core% webapps/clientwar/core%g' {} +
find . -type f -exec sed -i 's% window.open("/mywar/"% window.open("/clientwar/"%g' {} +
find . -type f -exec sed -i 's%Disallow: /mywar/%Disallow: /clientwar/%g' {} +
find . -type f -exec sed -i 's%http://localhost:8080/mywar/%http://localhost:8080/clientwar/%g' {} +
find . -type f -exec sed -i 's%http://localhost:9200/mywar/%http://localhost:9200/clientwar/%g' {} +


However, though it looks very readable, it's not compact, and many commands really look like others.

And, worst of all, it's quite slow: more or less 1 hour for the whole set of commands to run on my 2-years old laptop...

Any advice on how to make this:


more performant?
(optionally) better written (if it stays easy to read and understand)?
There's a gross inefficiency in this script: not only are we opening each file n times (where n is the number of lines), we're also running n find instances.

Instead, consider running find just once, and using a single sed command to perform the substitutions.  The easiest way to do that is to make it an executable script (with a #! line):

#!/bin/sed -f

s% '/mywar/% '/clientwar/%g
s%,'/mywar/%,'/clientwar/%g
s% "/mywar/% "/clientwar/%g
s% file="/mywar/% file="/clientwar/%g
s%&lt;TAB&gt;href="/mywar/%&lt;TAB&gt;href="/clientwar/%g
s% href="/mywar/% href="/clientwar/%g
s% name="/mywar/% name="/clientwar/%g
s% relativePath="/mywar/% relativePath="/clientwar/%g
s% requestUrl.indexOf("/mywar/")% requestUrl.indexOf("/clientwar/")%g
s% src='/mywar/% src='/clientwar/%g
s%&lt;TAB&gt;src="/mywar/%&lt;TAB&gt;src="/clientwar/%g
s% src="/mywar/% src="/clientwar/%g
s% url('/mywar/% url('/clientwar/%g
s% url("/mywar/% url("/clientwar/%g
s% url(/mywar/% url(/clientwar/%g
s% url="/mywar/% url="/clientwar/%g
s% value="/mywar/% value="/clientwar/%g
s% webapps/mywar/core% webapps/clientwar/core%g
s% window.open("/mywar/"% window.open("/clientwar/"%g
s%Disallow: /mywar/%Disallow: /clientwar/%g
s%http://localhost:8080/mywar/%http://localhost:8080/clientwar/%g
s%http://localhost:9200/mywar/%http://localhost:9200/clientwar/%g


We can now run that for every file:

find . -type f -exec scriptname.sed -i {} +


Or (with GNU Find and Parallel), we can use as many processor cores as we have available:

find . -type f -print0 | parallel -0 -X scriptname.sed -i




We can combine some of the search patterns.  For example, consider these three substitutions:

s% '/mywar/% '/clientwar/%g
s%,'/mywar/%,'/clientwar/%g
s% "/mywar/% "/clientwar/%g


They can be replaced with a single substitution, using \1 to retain the part we want to keep unchanged:

s%\([ ,]'\| "\)/mywar/%\1/clientwar/%g


This can be extended to almost all the substitutions (excepting only the ones that need to match text beyond the end of mywar/).

If all those backslashes are irritating, consider using (GNU) grep's -r option to enable extended regular expressions (but then you'll need to escape the literal ( that are to be matched, so it might not be worth it).