Coder Perfect

sed in-place flag that works both on Mac (BSD) and Linux

Problem

Is there a way to use sed to perform in-place editing without making a backup that works on both Linux and Mac? While the BSD sed shipped with OS X seems to need sed -i ” …, the GNU sed Linux distributions usually come with interprets the quotes as empty input file name (instead of the backup extension), and needs sed -i … instead.

Is there a command line syntax that works for both variants so that I can use the same script on both systems?

Asked by dnadlinger

Solution #1

If you truly want to use sed -i the’simple’ method, the following works on both GNU and BSD/Mac sed:

sed -i.bak 's/foo/bar/' filename

Take note of the lack of space as well as the dot.

Proof:

# GNU sed
% sed --version | head -1
GNU sed version 4.2.1
% echo 'foo' > file
% sed -i.bak 's/foo/bar/' ./file
% ls
file  file.bak
% cat ./file
bar

# BSD sed
% sed --version 2>&1 | head -1
sed: illegal option -- -
% echo 'foo' > file
% sed -i.bak 's/foo/bar/' ./file
% ls
file  file.bak
% cat ./file
bar

Obviously, you could just remove the.bak files at that point.

Answered by kine

Solution #2

On GNU sed, this works, but not on OS X:

sed -i -e 's/foo/bar/' target.file
sed -i'' -e 's/foo/bar/' target.file

On OS X, this works, but not with GNU sed:

sed -i '' -e 's/foo/bar/' target.file

On OS X, you can

Answered by dnadlinger

Solution #3

Because most programs were written for GNU sed versions, I always install GNU sed via Homebrew on OSX to avoid difficulties in scripts.

brew install gnu-sed --with-default-names

Then GNU sed will take the place of your BSD sed.

You can also install without default-names, but this will result in:

Answered by Lewy

Solution #4

Why can’t you use Perl, as Noufal Ibrahim points out? Perl is present on every Mac, and very few Linux or BSD distributions do not have Perl as part of the base system. BusyBox (which functions similarly to GNU/Linux for -i, except that no backup extension can be supplied) is one of the few environments that might truly lack Perl.

As ismail recommends,

Scripts, aliases, or other workarounds to deal with the underlying incompatibility of sed -i between GNU/Linux and BSD/Mac appear to be a superior answer in virtually every scenario.

Answered by Alex Dupuy

Solution #5

It’s not possible to make it function.

One option is to create a temporary file, such as:

TMP_FILE=`mktemp /tmp/config.XXXXXXXXXX`
sed -e "s/abc/def/" some/file > $TMP_FILE
mv $TMP_FILE some/file

This is effective on both sides.

Answered by analogue

Post is based on https://stackoverflow.com/questions/5694228/sed-in-place-flag-that-works-both-on-mac-bsd-and-linux