おもこん

おもこんは「思いつくままにコンピュターの話し」の省略形です

ファイルシステムの微妙な違いに悩まされた話

最近Rubyをやってました

最近Rubyである程度の機能をつけたコピープログラムを作っていました。2つのディレクトリ内を再帰的に比較して同じファイルがあったら、新しいファイルの方を古いファイルに上書きする。結果として2つのディレクトリが新しいものに更新されて同一のものになる、というプログラムです。これだけならすでにそういうコマンドはあるわけですが、コピーの対象から除くファイルを指定できるなどの追加機能を含めたのでrubyで作りました。

タイムスタンプ

タイムスタンプがファイルシステムによって異なることは、ソフトウェアのエンジニアの中では有名かもしれません。私はそのへんの事情に気づかずにプログラムしていてバグに悩みました。Linuxのファイルシステムは時間の精度が高いのですが、USBのファイルシステムがFAT32で時間の精度が低いのです。それで、LinuxからUSBにファイルをコピーすると、(たぶん)切り捨てがおこり、USBの方がほんの少し古いファイルになります。それで、タイムスタンプを比較して新しいファイルを古いファイルのコピーするのですが、この誤差のためにファイルの書き換えがなくてもコピーするということになってしまいました。

本質的な解決になっているかわかりませんが、時間を整数に変換して細かい部分を切り捨てて時間比較することによって期待通りに動作するようになりました。このバグが分かるまで半日くらいかかってしまいました。

ファイル名

これは、知っていたことなのですが、Linuxは大文字小文字を区別するのに対してWindowsは区別しません。それで、Linux側に大文字小文字の違いだけでアルファベットの同じファイルがあるとまずいことになります。例えば、ABC.txtとabc.txtはUSB側では同じファイル名と考えられます。Linux側にこの2つのファイルがあり、USB側にABC.txtのみがあると、
ABC.txt と ABC.txt を比較する => 新しいものから古いものへコピー
abc.txtとABC.txtを比較 => 新しいものから古いものへコピー、ただし、コピー先はABC.txt名になる。
USBでは同名のファイルとみなされるので、大文字小文字の違う2種類のファイルを置くことができないのです。
これも気がつくまで結構時間がかかりました。ダメですね。トホホな話です。これは、Linux側で同名で大小文字の違いだけのファイルを作らないようにするしかありません。

ファイルのバックアップやミラーのシステムではタイムスタンプが問題になるかもしれない

システムを作る側は、ユーザがどのようなファイルシステムにバックアップするか分かりませんので、対処は難しいものがあります。バックアップ用のファイルシステムを指定してしまうか、代表的なファイルシステムに対する対処法をオプションで用意しておくか、ということになるかと思います。

今回ハマってしまったので、備忘録として書きました。