64

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 .
Amir Afghani
  • 7,203
  • 11
  • 27
  • 23
  • 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 '12 at 19:05
  • 1
    Actually, that solves it, at least for me. Both double and single quotes should be substituted by " and ', respectively. – Lev Levitsky Apr 18 '12 at 19:07
  • 4
    Smart(?) quotes! .. :) – Peter.O Apr 18 '12 at 19:09
  • What I pasted was exactly what I was running. Can someone post an answer? – Amir Afghani Apr 18 '12 at 20:17
  • @AmirAfghani Does find . -name "*.java" -exec sed -i 's/foo/bar/g' {} \; work for you? (copy and paste it to the terminal). If so, I think Mikel could post it as an answer. – Lev Levitsky Apr 18 '12 at 20:23
  • 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 '12 at 02:43
  • 1
    Sorry was at work when I posted this -- I agree Mikel – Amir Afghani Apr 19 '12 at 02:53

1 Answers1

86

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.

sinback
  • 103
janos
  • 11,341