要旨
sedでファイルを直接書き換えようとした際に、-iのサフィックスの振る舞いが Linux(GNU) と Mac(BSD) で異なります。
GNU Style
sed -i -e 's/foo/bar/g' file.txt # バックアップ作成されない
sed -i.bak -e 's/foo/bar/g' file.txt # file.txt.bakが作成される
BSD Style
sed -i '' -e 's/foo/bar/g' file.txt # バックアップ作成されない
sed -i '.bak' -e 's/foo/bar/g' file.txt # file.txt.bakが作成される
エイリアスを使った方法は
https://qiita.com/narumi_888/items/e425f29b84da6b72ad62
で紹介されていますが、この記事は sed のまま使いたい、既存のスクリプトを書き換えたくない人向けです。
こんな人向け
- シェルスクリプトで sed を iオプション 付きで使う
- Linux(GNU sed)とMac(BSD sed)の開発者が混在している
- Macの開発者にGNU sedへの入れ替えを強要するのはちょっと・・・
- エイリアスはなんか嫌だ
解決
sedというシェル関数を定義し、正しい振る舞いに書き換えます。
function sed(){
# sedコマンドオーバーライド
# macOS標準の BSD sed は GNU sed の-iオプション指定方法と異なるので、GNUに合わせるようオーバーライドする
if command sed --version 2>&1 | grep -q GNU; [ $? -ne 0 ] \
&& [ "${1:0:2}" == "-i" ]
then
# BSD sed かつ -iオプション有り
# -iオプションの拡張子を書き換える
BACKUP_EXT=${1:2}
shift
command sed -i "$BACKUP_EXT" "$@"
return $?
else
# sedコマンドそのまま実行
command sed "$@"
return $?
fi
}