3
\$\begingroup\$

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%<TAB>href="/mywar/%<TAB>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%<TAB>src="/mywar/%<TAB>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:

  1. more performant?

  2. (optionally) better written (if it stays easy to read and understand)?

\$\endgroup\$
3
\$\begingroup\$

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%<TAB>href="/mywar/%<TAB>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%<TAB>src="/mywar/%<TAB>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).

\$\endgroup\$
  • \$\begingroup\$ Clear, complete and explained -- Something from which I can learn! Exactly what I was searching for when coming here... Thanks a lot. \$\endgroup\$ – user3341592 Oct 27 '17 at 14:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.