sed -i オプションが動作しない原因と対処(MacとLinuxの違い)

  • URLをコピーしました!
目次

はじめに

Linuxでよく使われる sed -i オプションは、**ファイルを直接書き換える(インプレース編集)**ために利用されます。

ところが、同じコマンドをMacで実行すると、以下のようなエラーが出て動かないことがあります。

$ sed -i 's/foo/bar/' sample.txt
sed: 1: "sample.txt": invalid command code s

この記事では、なぜLinuxとMacで挙動が違うのか、そして どう対処すればよいのか を解説します。

原因:BSD版 sed と GNU sed の違い

  • Linux に入っているのは多くの場合 GNU sed
  • macOS に入っているのは BSD版 sed

この2つで -i オプションの仕様が異なる ため、同じコマンドでも挙動が変わります。

GNU sed(Linux)の場合

Linux環境では以下のように -i を単独で指定可能です。

sed -i 's/foo/bar/' sample.txt

この場合、sample.txt が直接書き換えられます。

バックアップを取りたいときは拡張子を指定します:

sed -i.bak 's/foo/bar/' sample.txt

→ 元のファイルは sample.txt.bak として保存されます。

BSD版 sed(macOS)の場合

Macの sed では、-i オプションに 必ず引数(拡張子)を与える必要がある という仕様があります。

エラーになる例

sed -i 's/foo/bar/' sample.txt

正しい使い方

バックアップを取らない場合

空文字 '' を指定します。

sed -i '' 's/foo/bar/' sample.txt

バックアップを取る場合

拡張子を与えます。

sed -i '.bak' 's/foo/bar/' sample.txt

→ 元のファイルが sample.txt.bak として残ります。

実務での対応方法

1. MacとLinuxで同じスクリプトを使う場合

環境ごとに sed の種類を判別して処理を分けるのが安全です。

if sed --version >/dev/null 2>&1; then
  # GNU sed
  sed -i 's/foo/bar/' sample.txt
else
  # BSD sed (macOS)
  sed -i '' 's/foo/bar/' sample.txt
fi

2. MacでGNU sedを使う

HomebrewでGNU sedをインストールすれば、Linuxと同じ書き方が可能です。

brew install gnu-sed

インストール後は gsed コマンドとして利用できます。

gsed -i 's/foo/bar/' sample.txt

まとめ

複数環境で使う場合は、条件分岐するかGNU sedを導入するのが確実。

sed -i がMacで動かないのは BSD sedとGNU sedの仕様違い が原因。

Macのsedは -i に必ず引数が必要。空文字 '' を指定するのがポイント。

よくあるエラーと解決方法まとめ
目次