ShellScript
Bash
Zsh

シェルスクリプトでリダイレクトによる上書き防止

More than 3 years have passed since last update.


bash

bash では set -C もしくは set -o noclobber とやれば、リダイレクトによる上書きを禁止できます。


-C 設定されている場合、 bash はリダイレクト演算子 >, >&, <> で既存のファイルを上書きしません。上書きができるのは、リダイレクト演算子 >| を > の代わりに使った時です。


man にあるように リダイレクト演算子を >| にすればオプションに関係なく上書き可能です。


bash

# まだ上書きできる

$ touch hoge.txt
$ echo hoge >hoge.txt

# 上書きを禁止(set -o noclobber でも可)
$ set -C
$ echo hoge >hoge.txt
-bash: hoge.txt: cannot overwrite existing file

# >| を使えば禁止状態でも上書きできる
$ echo hoge >|hoge.txt

# set +C で上書き禁止状態を解く(set +o noclobber でも可)
$ set +C
$ echo hoge >hoge.txt


set -C で上書きを禁止の状態で >> によるファイル作成はできます。>> は追記をするときに使用するリダイレクションですが、ファイルがない場合は新規作成することができます。


zsh

zsh では以下のオプションでリダイレクトによる上書きを禁止にできます。

setopt noclobber

また、実はこれを設定しないでもデフォルトで有効になっていますので初期状態で上書きはできません。

bash と同様に初期状態では上書きできます(setopt clobber)。手違いなどで上書きをしてしまわぬよう、setopt noclobber しているとき、上書きしたい場合は >|>! を使います。


zsh

# 最初から上書き不可(setopt noclobber で明示的にしても良い)

$ echo hoge >hoge.txt
zsh: file exists: hoge.txt

# 上書き禁止状態でも無理に上書きする
$ echo fuga >|hoge.txt
$ echo hoge >!hoge.txt

# bash と違ってファイルがない場合は >> による新規作成が出来ない
$ echo hoge >>newfile
zsh: no such file or directory: newfile

# 先程と同様に >>| か >>! を使えば新規作成できる
$ echo fuga >>|newfile
$ echo hoge >>!newfile

# 上書き禁止を解除
$ setopt clobber
$ echo hoge >hoge.txt



まとめ

bash と zsh の互換性があるのは >|>>| です(>! は bash がサポートしていません)。なので、bash でも zsh でも使えるスクリプトを書きたい場合は前者の書き方をするといいでしょう。

参考