One Liner
Node.jsベースであるAtomのpackageには階層がとても深いnested node_modulesを生成するものがあるので、Winodwsの標準的な機能ではパス名の制約により削除できなくなる。
事の起こり
11月13日、Atomの1.2がリリースされた日のこと。
その頃、会社でWindows8.1環境に入れたAtomがかなり不調で、またAtom本体の自動アップデートがかかるとインストール済みのpackageがAtomの最新バージョンに未対応というエラーメッセージを出す現象が頻繁に起こっていたので、1.2が出たのを機にAtomのクリーンインストールをすることにした。1.2ではElectronやらnode.jsなどのAtomの根幹的な部分でのアップデートがあるし。
さて、Windows環境でのAtomのアンインストール方法であるが、以下の手順を踏んだ。
- まずいつもおなじみの手順、コントロールパネルの「プログラムのアンインストールまたは変更」でAtomを選択してアンインストール
- さらにエクスプローラーからユーザーフォルダにあるC:\Users\xxx\.atomを選択して削除、、、できない?
「フォルダーには名前が長すぎる項目が含まれていてごみ箱に移動できません」
なんですか、それ?
原因
- インストールされたAtomのpackageはWindows環境ではユーザーフォルダのC:\Users\xxx\.atom\package以下に配置される
- このpackage(とりあえずhogeとする)がnpmのモジュールに依存している場合、そのモジュールはC:\Users\xxx\.atom\package\hoge\node_modulesに配置される。
- 配置されたnpmモジュールが別のnpmモジュールに依存している場合、そのモジュールは依存元のnpmモジュールのnode_modulesに配置される。hogeが依存するnpmモジュールをare,areが依存するモジュールをkoreとすると、koreが配置されるパスは以下のようになる
C:\Users\xxx.atom\packages\hoge\node_modules\are\node_modules\kore
このモジュールkoreが依存するモジュールをsoreとすると...というプロセスが繰り返されるとnode-modulesのネストがどんどん深くなる。以下はatom-beautify package以下にあるnode-modulesフォルダの例である。
C:\Users\xxx.atom\packages\atom-beautify\node_modules\atom-message-panel\node_modules\space-pen\node_modules\grim\node_modules\emissary\node_modules\es6-weak-map\node_modules\es5-ext\node_modules\es6-symbol
1.このnode-modulesのネストが深くなる現象はnode.jsの立場では即座に問題とはならない。Windows版のnode.jsはNTFSの長いパス名に対応している。許容されるパス名の最大長は32768文字で、実用上は十分な範囲と思われる。
2. 問題はWindowsのOSがNTFSの長いファイル名に対応していないことである。Windows環境では互換性維持のためにパスの最大長はパスは最大260文字までに制限されている。そのためWindowsのエクスプロラーやコマンドラインでは260文字を越えるパス名を生成できない。
3. やっかいなのはこの260文字制限が削除に対しても適用されることで、よってWindowsの標準的な機能の範囲では260文字を越えるパス名のファイルやフォルダーは削除できない。
4. その一方でAPIを使えば260文字を越えるパス名のファイルやフォルダーが生成できるので、node.jsなどの非標準的なアプリケーションが生成した260文字を越えるパス名のファイルやフォルダーが、エクスプローラーなどの標準的機能では削除できないという奇妙な現象が発生する。
これはnode.js方面ではnested node_modulesのWindows非互換性として知られている問題(ex https://github.com/nodejs/node-v0.x-archive/issues/6960 )であるが、この件について言及している日本語の文献は少ないようである。筆者はQAサイトの質問事例以外では見かけなかった。日本ではnode.jsというか先端的なJavascriptの開発者が開発環境として概ねMacOSXかLinuxを使っていてWindowsユーザーが少ないので1、この問題に直面する機会が少ないからであろう。2
対策
この長すぎるパス名の問題は多くの人が悩まされているようで、「Windows 長いファイル名 削除」というキーワードで検索すると多くの事例が出てくる。以下はQiita内の事例
「フォルダーには名前が長すぎる項目が含まれていてごみ箱に移動できません」
これらの知見を総合すると解決策は以下の三つに集約されるようだ
- 長いパス名に対応したツールを使う
- 長いパス名を削除するプログラムやスクリプトを書く
- 長すぎるパス名の途中の階層のフォルダにネットワークドライブを割り当てて削除するパスの長さを260文字未満にする。
技術者としては当然2の方法でやるべきだろうが、筆者は面倒くさがりなので3の方法を用いた。といっても途中の階層にネットワークドライブを割り当てるのではなく、深いフォルダの先頭のあたりを移動して長すぎるパスの長さを少しづつ削っていくというやり方にしました。もっとも途中で削除プログラムを書いた方がよかったとかなり後悔しました。
というわけで、WindowsでAtomというかWindows環境以外から来たツールなり技術なりを使うといろいろ面倒な現象に遭遇しますが、めげずにがんばりましょう。
では皆さん、Merry Christmas!
-
Paul Grahamの2007年の予言が未だに有効というのが驚かされるが、そろそろ賞味期限切れか。( http://www.paulgraham.com/microsoft.html ) ↩
-
未確認だがMacOS Xではパス名の長さが2024文字、ただし実用上は1024文字という制限があるらしいので似たような問題が起きる可能性はありうる。 ↩