うまいぼうぶろぐ

linuxとhttpdとperlのメモ

bashでファイルのリダイレクトによる上書きを防止するオプション

自分が運用する環境では、うっかりrm、mv、cpでファイルを消さない/上書きしないようにbashのaliasの機能を使って"-i"オプションを有効にしています。

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'

これはこれでいいんですが、このaliasはうっかりファイルリダイレクトの前には無力です。例えば圧縮されているログをパイプでごにょごにょした結果をリダイレクトして、テキストに出力したいとする。

# zcat hoge.gz | sed -e 's/hoge/fuga/g' | sort -k1 -n > output.txt

このとき寝ぼけて、zcat > hoge.gz などとやってしまうと地獄を見ます><

なのでうっかりしても大丈夫なようにリダイレクトを禁止してしまおう。bashではset -C もしくはset -o noclobber とやれば、リダイレクトによる上書きを禁止できます。
(manにあるように リダイレクト演算子を">|"にすればオプションに関係なく上書き可能)
man bash のsetの項目参照。

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

$ touch hoge.txt
$ echo hoge > hoge.txt
#### -Cオプションを有効にする
$ set -C
$ echo hoge > hoge.txt
-bash: hoge.txt: cannot overwrite existing file
#### ">|"だと上書きできる
$ echo hoge >| hoge.txt

オプションを元に戻す場合はset +C もしくはset +o noclobberを実行する。

というわけで、.bashrcにはaliasの他に

set -C

を追加しておけば少しは幸せになるかも。ただ、aliasと違って一見分かりにくい(気がする?)ので、set -Cを設定してることを忘れてしまうと無駄にはまりそう。chattr +i して削除禁止にしたこと忘れてて、ファイル消せない!ってまごまごしたことある俺みたいな人間には注意して設定する必要ありますね。