65

I'm using the following command on my mac:

$find . -name “*.java” -exec sed -i ’s/foo/bar/g’ {} \;

and it seems to have no effect.

I have two files in the directory that end in .java, which both have the foo text in them. Am I missing something?

EDIT : Results from request of comments

[aafghani-03:~/test amirafghani]$ find . -name "*.java" -exec sed -i 's/foo/bar/g' {} \;
sed: 1: "./bar.java": invalid command code .
sed: 1: "./foo.java": invalid command code .
7
  • 3
    Is that exactly what you're running? What if you remove the -exec and everything after it? Does it print the names of the Java files? (I'm worried that you're using smart quotes instead of ASCII quotes.)
    – Mikel
    Apr 18, 2012 at 19:05
  • 1
    Actually, that solves it, at least for me. Both double and single quotes should be substituted by " and ', respectively. Apr 18, 2012 at 19:07
  • 4
    Smart(?) quotes! .. :)
    – Peter.O
    Apr 18, 2012 at 19:09
  • 2
    Next time please post the error message you are seeing when you ask the question. It will save time for everyone.
    – Mikel
    Apr 19, 2012 at 2:43
  • 1
    Sorry was at work when I posted this -- I agree Mikel Apr 19, 2012 at 2:53

1 Answer 1

87

First of all, make sure you're using regular ascii quotes like " and ' (ascii codes 0x22 and 0x27, respectively) in shell scripts, because the example in your post contains non-standard quote characters. If you look closely, they look a bit different. Most probably this is a copy-paste error from a rich text document format like Word, OOWriter, or even a browser window.

Since you're on a Mac, you most probably have the FreeBSD implementation of sed, in which case you have to write the command this way:

find . -name "*.java" -exec sed -i '' "s/foo/bar/g" {} +

(here using + instead of \; to avoid running one sed invocation per file).

Note that those quotes around "s/foo/bar/g" are necessary if foo or bar have spaces.

In the FreeBSD implementation of sed the -i flag needs an argument: the extension of a backup file. For example with -i .bak the command would backup file1.txt as file1.txt.bak first before performing the replacement in the original file. Using an empty argument '' means to not use a backup file, which seems to be what you want.

The same thing in the GNU (or NetBSD, OpenBSD, busybox) implementation would be:

find . -name "*.java" -exec sed -i "s/foo/bar/g" {} +

Thank you @bahamat and @Mikel and @pieter-breed for improving my answer with your comments.

4
  • 3
    What do the curly braces do? May 14, 2018 at 20:45
  • 8
    @ZaneHitchcox the curly braces are placeholders for the matched filename
    – janos
    May 15, 2018 at 6:32
  • what's the + do at the end?
    – Anthony
    Feb 7, 2020 at 23:46
  • 3
    @Anthony the + at the end terminates the list of arguments of the -exec option. It is required by the syntax of -exec.
    – janos
    Feb 8, 2020 at 15:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .