51

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

67

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
  • 2
    What do the curly braces do? May 14, 2018 at 20:45
  • 6
    @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
  • 1
    @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

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.