コンピューターサイエンス:アルゴリズム / OS / ネットワーク / DB
ext4 / APFS / NTFS の違い
Mac では動いたのに、デプロイしたら Module not found
import UserCard from "./components/userCard" と書いたコードが、手元の Mac では通り、Linux のサーバーでは落ちる。実体のファイル名は UserCard.tsx です。Web 開発で最も多く踏まれる環境差の 1 つです。
原因は言語でもビルドツールでもなく、名前を突き合わせるときの規則です。macOS の APFS は既定で大文字と小文字を同じ文字として扱い、Linux の ext4 は別の文字として扱います。ディレクトリの表を引く処理が、片方は大小を無視する比較で、もう片方はバイト列そのままの比較だ、という違いです。
名前の扱いが揃わない理由
ファイル名は結局バイト列ですが、それを何とみなすかは各実装が決めます。ext4 はバイト列をそのまま比較します。何も解釈しないので、日本語だろうが絵文字だろうが、バイトが 1 つ違えば別ファイルです。
APFS は Unicode として解釈します。しかも macOS には「が」を か と濁点の 2 文字に分解した形で保存してきた経緯があり、同じ名前に見えるのに Git が延々と差分を出す、ZIP を Windows で開くと名前が崩れる、といった事故はここから来ます。
この差は好みの問題ではなく、設計時の要請の違いです。GUI を前提とする macOS や Windows は「利用者が Memo.txt と memo.txt を別物だと思わない」ことを優先しました。サーバー用途で育った ext4 は、余計な解釈をしないことを優先しました。どちらも、その場では正しい判断でした。
前提とする装置の違いも効いています。ext4 が広まったのは HDD が主流の時代で、磁気ヘッドの移動を減らすためにブロックをなるべく連続させる設計です。APFS は SSD しか無い前提で作られ、書き換えのたびに別の空き場所へ書く方式を採っています。どこが速いかは装置で変わるので、答えも 1 つに収束しません。
揃えられるのは呼び方までで、名前の規則は漏れてくる
VFS のおかげで、open や read の呼び方は下にどの実装が居ても同じです。だから普段は種類を意識せずに済みます。
しかし共通化できるのは手続きの形までで、名前をどう突き合わせるかは各実装の内側にあります。ここだけは上のアプリまで漏れてきます。ファイル名の大小を意識しないコードは、動く環境と動かない環境ができてしまいます。
ターミナル
touch UserCard.tsx
cat userCard.tsxプレーンテキスト
macOS (APFS) 中身が表示される
Linux (ext4) cat: userCard.tsx: No such file or directory対策は環境をそろえることに尽きます。Linux へデプロイするプロジェクトは Docker や Lima の中で開発する、あるいは大小を区別する設定の APFS ボリュームを別に切って、そこにリポジトリを置きます。
現場の話 外付け SSD を Mac と Windows で共用したいときは exFAT を選びます。NTFS は macOS からは読めても書けず、APFS は Windows が認識しません。ただし exFAT は障害に弱いので、消えて困るデータの唯一の置き場所にはしないでください。