360

Being forced to use CVS for a current client and the address changed for the remote repo. The only way I can find to change the remote address in my local code is a recursive search and replace.

However, with the sed command I'd expect to work:

find ./ -type f -exec sed -i "s/192.168.20.1/new.domain.com/" {} \;

I get an error for every file:

sed: 1: ".//file/path ...": invalid command code .

I've tried to escape the periods in the sed match/replacement but that doesn't solve anything.

7 Answers 7

831

If you are on a OS X, this probably has nothing to do with the sed command. On the OSX version of sed, the -i option expects an extension argument so your command is actually parsed as the extension argument and the file path is interpreted as the command code.

Try adding the -e argument explicitly and giving '' as argument to -i:

find ./ -type f -exec sed -i '' -e "s/192.168.20.1/new.domain.com/" {} \;

See this.

Sign up to request clarification or add additional context in comments.

19 Comments

If you spent 10 min like I did finding the difference, it is -e option
This question answers the RE error: illegal byte sequence on MacOS.
i used an empty string '' as the parameter for -i and that worked, like sed -i '' 's/blah/xx/g'
For me, adding -e after -i made sed backup all my files in this way: "foo.txt" -> "foo.txt-e". Obviously what I wanted was rather -i '', i.e. don't backup changed files.
Same problem for me. This -i -e combined with a find resulted in many many files ending in -e-e-e-e-e-e-e.
|
133

On OS X nothing helps poor builtin sed to become adequate. The solution is:

brew install gnu-sed

And then use gsed instead of sed, which will just work as expected.

6 Comments

Thank you for this answer, which worked great for me! Working on both Linux and Mac, I'd much prefer access to a familiar tool than learning arcane differences between two closely related ones.
Thanks - worked for me too. A nice little tip is to set up an alias like alias sed='gsed' to make the alignment between macOS and linux complete.
This worked perfectly for me too. Begs the question -- why is macOS sed different? Why? I mean, why???
@ChrisMiller, MacOS is based on BSD technology, not on GNU/Linux. Hence sed is the bsd variant.
this worked for me on a Mac, thank you Dmitry, created:
|
68

You simply forgot to supply an argument to -i. Just change -i to -i ''.

Of course that means you don't want your files to be backed up; otherwise supply your extension of choice, like -i .bak.

Comments

9

Simply add an extension to the -i flag. This basically creates a backup file with the original file.

sed -i.bakup 's/linenumber/number/' ~/.vimrc

sed will execute without the error

Comments

3

It is not the case for the OP but it was for me and could help someone else.

If you are using ' to enclose regex, double check the ' characters. I was copying and pasting the script from word processing and it was pasting ' as in bash.

4 Comments

The OS generally does no such thing. Did you copy/paste from a blog or a word processor or something?
@tripleee you're right! Updated my answer.
So the real lesson here is never use a word processor for code. There are some blog platforms which unfortunately apply "styling" to code and thus breaking it, which you as a consumer of that blog can't really do much about.
(Also, irritatingly, the keyboard substitution facility on IOS will "helpfully" replace ASCII quotes with "typographic" ones no matter what you do, so it's not great for saving snippets of code.)
2

Probably your new domain contain / ? If so, try using separator other than / in sed, e.g. #, , etc.

find ./ -type f -exec sed -i 's#192.168.20.1#new.domain.com#' {} \;

It would also be good to enclose s/// in single quote rather than double quote to avoid variable substitution or any other unexpected behaviour

Comments

1

To convert this find command for macOS, we need to handle the -i option correctly for sed. Here’s how it should look:

find ./ -type f -exec sed -i '' "s/192.168.20.1/new.domain.com/g" {} +

Explanation of Changes

  1. -i '': The -i option in macOS sed requires a backup extension. -i '' (an empty string) tells it to edit files in place without creating a backup.
  2. +: The + after {} tells find to pass multiple files to sed at once, which is more efficient than running sed separately on each file (optional but useful for larger directories).
  3. g: Added g at the end of the sed expression (s/192.168.20.1/new.domain.com/g) to replace all occurrences of 192.168.20.1 in each line, not just the first occurrence.

This should now work on macOS as expected.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.