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?

  • 1
    As an aside, you don't need single quotes around {}, and -name "*" is superfluous.
    – Wildcard
    Feb 26 '16 at 3:08

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:

  • If you're already using a backreference, there's no reason not to include hello in it. And putting one curly brace in brackets should be enough; you don't need to do both.
    – Wildcard
    Feb 26 '16 at 3:04
  • (And you don't need single quotes around {}.)
    – Wildcard
    Feb 26 '16 at 3:04
  • 1
    find "$dir" -type f -exec sed -i 's/\(hello[{]}\)a/\1b/g' {} +
    – Wildcard
    Feb 26 '16 at 3:10

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 {} \;
  • 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 2: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 3:09

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.