6

I'm wondering if it is possible to include empty curly braces {} inside a sed replacement called from a find -exec.

An example:

find "$dir" -type f -name "*" -exec sed -i s/hello{}a/hello{}b/g '{}' +

This brings up the error message of duplicate {}:

find: Only one instance of {} is supported with -exec ... +

Is there a way to keep {} in the sed command and to be seen as literals, not as replacements for the files that find finds?

mrbnnny
  • 263

2 Answers2

7

In this case, you can work around find's exec grammar by capturing a brace expression and using a back reference in the replacement text:

$ cat f1 f2
f1: hello{}a
f2: hello{}a
$ find . -type f -exec sed -i 's/hello\([{][}]\)a/hello\1b/g' '{}' +
$ cat f1 f2
f1: hello{}b
f2: hello{}b

Or, more simply (as noted in the comments):

find "$dir" -type f -exec sed -i 's/\(hello[{]}\)a/\1b/g' {} +

Note that the -i option for Sed is not portable and will not work everywhere. The given command will work on GNU Sed only.

For details, see:

Barefoot IO
  • 1,946
0

For one thing, you're using + which means that -exec can put multiple arguments in place of {}. There's no way this is what you intended when combined with your sed command, and it's possible (though very implementation-dependent) that you can get the result you want by simply removing the +.

However the general way to do this is by using sh -c:

find "$dir" -type f -exec sh -c 'sed -i "s/hello$1a/hello$1b/g" "$1"' sh {} \;
Wildcard
  • 36,499
  • 1
    I should have been more clear in my original question. I do want multiple arguments. I want the {} in the sed command to be seen as literal braces, not as replacements for the files the find command finds. – mrbnnny Feb 26 '16 at 02:43
  • @mrbnny, fair enough. In that case Barefoot IO's answer is what you need (though it can be simplified—see my comments on that answer). – Wildcard Feb 26 '16 at 03:09