0
for i in `ls`; do find /path/to/different/project -name $i -type f -exec sed -i "s/var Handlebars/d" {}; done;

I have tried seemingly everything, including escaping the ; after the {}, escaping both ;'s, escaping the quotes, tweaking the sed command - all to no avail. What gives?

papiro
  • 2,158
  • 1
  • 20
  • 29

3 Answers3

3

(Don't use for i in ls. It will fail if any filename includes whitespace, and it is unnecessary. for i in * does exactly what you want, without the need for a subprocess.)

The correct syntax is:

for fn in *; do
  find /path/ -name "$fn" -type f -exec sed ... {} \; ;
done  

\; is an argument to find. Both {} and ; must appear as individual arguments; if you use {}\; the shell will combine those into one argument and find will treat it as a simple argument to sed.

The second ; is a shell metacharacter which terminates the find command. Written as above, on three lines, the ; is unnecessary but if you want a one-liner, it will be needed. If you escape it, as \;, it stops being a shell metacharacter, and is simply passed to find as an argument, where it will create an error.

rici
  • 234,347
  • 28
  • 237
  • 341
  • `for i in \`ls\`; do find /path/ -name $i -type f -exec sed -i "s/var Handlebars/d" {}\; ; done;` This is failing for me as well. – papiro May 31 '16 at 17:10
  • @papiro please read my answer again. It specifically mentions that error. – rici May 31 '16 at 17:49
  • `for i in \`ls\`` was working just fine for me (none of my filenames included whitespace). – papiro May 31 '16 at 17:55
  • The other error you specifically mention is created if you escape _both_ semi-colons, which is not the problem I'm describing. – papiro May 31 '16 at 18:28
2

the sed command as written will fail, as sed expects 2 args to the s command. Are you attempting to delete all lines where "var Handlebars" exist, if so, then the correct way (with sed) will be

sed '/^.*var Handlebars.*$/d'

which is saying "delete (the 'd' command to sed) any line that contains the string 'var Handlebars'"

The anchors ^ and $ are beginning of line and end of line respectively, with the '.*' meaning zero or more of any character before and after the 'var Handlebars' string.

so your compound command now becomes:

for i in *; do find /path/ -name "$i" -type f -exec sed -i '/^.*var Handlebars.*$/d' {} \; done

Cwissy
  • 2,006
  • 15
  • 14
  • `sed -i "/var Handlebars/d"` seems to work just fine to delete any lines which include that string. – papiro May 31 '16 at 18:20
0

The issue was two-fold. rici was correct that there needed to be an extra semi-colon, but then after that it was still failing unless a space character was inserted between the {} and the \;. The final command looks like this:

for i in `ls`; do find /path/to/different/project -name $i -type f -exec sed -i "/var Handlebars/d" {} \;; done;

Note: I also removed the s (substitution) from the sed command per Cwissy's comment.

papiro
  • 2,158
  • 1
  • 20
  • 29
  • I clearly stated that you need a space after the {}, and my example shows that. I don't know what the point of asking questions is if you're not prepared to read the answers. – rici May 31 '16 at 18:06
  • I do not see that the space after the `{}` is clearly stated. In fact, nowhere in your answer does it mention the space. The only thing missing from my command to make it not throw the error was the extra semi-colon (which you did mention) and the space. All of the other information was unnecessary and confounded the answer even further. – papiro May 31 '16 at 18:25
  • 2
    " Both {} and ; must appear as individual arguments; if you use {}\; the shell will combine those into one argument" – rici May 31 '16 at 18:28
  • I see now! Sorry about that. I definitely didn't think about that deeply enough. Apologies. – papiro May 31 '16 at 18:30