会社で「Windowsだとシンボリックリンクが作れない」という話になった。 mklink
で作れると話したら驚かれたのでメモ。
導入が Windowsでシンボリックリンクを作る | Developers.IO と全く同じだなぁ...
環境
Windows 10 Pro 64bit v1909、コマンドプロンプト Version 10.0.18363.1139。
mklink コマンド
mklink [オプション] <link> <target>
で、シンボリックリンクなどのリンクを作成する。
link
はリンク作成先、 target
はリンクが指す実際のファイル/ディレクトリパスを、絶対パスまたは相対パスで指定する。
オプションで作成するリンクの種類が異なり、それぞれでファイルまたはディレクトリの指定可否が決まる。
オプション | 作成されるリンク | target指定先 |
---|---|---|
未指定 | ファイルのシンボリックリンク | ファイル |
/d |
フォルダのシンボリックリンク | ディレクトリ |
/h |
ハードリンク | ファイル |
/j |
ディレクトリジャンクション | ディレクトリ |
targetに相対パスを指定する際の注意
target
に相対パスを指定する場合、オプションによって、パスの起点となるディレクトリ位置が異なる。
未指定または /d
でシンボリックリンクを作成する場合は、 ln
と同様、 link
からの相対パスとなる。
/h
でハードリンクを作成、または /j
でディレクトリジャンクションを作成する場合、コマンド実行しているカレントディレクトリからの相対パスとなる。
リンクを作成するディレクトリをカレントディレクトリとすれば、どの方法でも同じ相対パスで指定できる。
コマンド例
以下のディレクトリ構成で、 link
ディレクトリ直下にリンクを作る場合。
C:\root ┣ target ┃ ┗ src ┃ ┗ exp.txt ┗ link
root直下でコマンド実行
リンク種類 | コマンド |
---|---|
ファイルのシンボリックリンク | mklink link\symlink_file ..\target\src\exp.txt |
フォルダのシンボリックリンク | mklink /d link\symlink_dir ..\target\src |
ハードリンク | mklink /h link\hardlink.txt target\src\exp.txt |
ディレクトリジャンクション | mklink /j link\junction target\src |
link直下でコマンド実行
リンク種類 | コマンド |
---|---|
ファイルのシンボリックリンク | mklink symlink_file ..\target\src\exp.txt |
フォルダのシンボリックリンク | mklink /d symlink_dir ..\target\src |
ハードリンク | mklink /h hardlink.txt ..\target\src\exp.txt |
ディレクトリジャンクション | mklink /j junction ..\target\src |
リンクの表示と確認
エクスプローラーでの表示
ファイルのシンボリックリンクは、ファイルの種類が「.symlink」、ファイルサイズが0になる。アイコンはファイルへのショートカットと同様。
また、ディレクトリのシンボリックリンクやディレクトリジャンクションは、アイコンはフォルダへのショートカットと同じだが、ファイルの種類は「ショートカット」ではなく「ファイル フォルダー」となる。
dirコマンドでの表示
dir
コマンドでの属性には、以下のように表示される。
また、シンボリックリンクやディレクトリジャンクションには、リンク先のファイルパスが表示される。
C:\root\link>dir /o:gn YYYY/MM/DD HH:MI <DIR> . YYYY/MM/DD HH:MI <DIR> .. YYYY/MM/DD HH:MI <JUNCTION> junction [C:\root\target\src] YYYY/MM/DD HH:MI <SYMLINKD> symlink_dir [..\target\src] YYYY/MM/DD HH:MI %FILE_SIZE% hardlink.txt YYYY/MM/DD HH:MI <SYMLINK> symlink_file [..\target\src\exp.txt]
相対パスでリンクを作成すると、シンボリックリンクの場合は ln
と同様、相対パスを保持しているが、ディレクトリジャンクションの場合は絶対パスに変換される模様。
相対パスで作成したシンボリックリンクを移動すると、移動先からの設定されている相対パスと同名のファイル/ディレクトリがない限りリンクを開けなくなるが、ディレクトリジャンクションを移動しても、リンク先のパスが変わらなければ、問題なく開くことができる。
lsコマンドでの表示
Git Bashから ls
コマンドを使うと、シンボリックリンクとディレクトリジャンクションには、Linuxなどでの実行結果と同様、ファイル名の後ろに @
がつく。
また、 ls -l
で、シンボリックリンクとディレクトリジャンクションにはリンク先のパスが表示される。
ディレクトリジャンクションは、絶対パス指定のディレクトリのシンボリックリンク扱いの模様。
$ ls -1 --group-directories-first junction@ symlink_dir@ hardlink.txt symlink_file@ $ ls -l --group-directories-first total 1 lrwxrwxrwx 1 ... 18 ... junction -> /c/root/target/src/ lrwxrwxrwx 1 ... 13 ... symlink_dir -> ../target/src/ -rw-r--r-- 2 ... 1 ... hardlink.txt lrwxrwxrwx 1 ... 21 ... symlink_file -> ../target/src/exp.txt
リンクの削除
作成されたシンボリックリンクや、ディレクトリジャンクションに対し、 unlink
のような削除用コマンドは用意されていない。
通常のファイルやディレクトリと同様、 rd/rmdir
や del
で削除可能。エクスプローラーからも削除できる。
ln コマンドとの違い
ln
コマンドは ln [OPTION]... [-T] TARGET LINK_NAME
なので、 mklink
とは link
と target
の順序が逆になる。
ln
で TARGET
に相対パス指定する際は、カレントディレクトリではなく LINK_NAME
からの相対パスにする必要があるので、 mklink
のほうがわかりやすい気もする。
一方、絶対パス指定であれば ln -s src dest
で指定できるので ln
のほうがシンプルか。
また、デフォルトではハードリンクが作成されるのも mklink
と異なる(あまり ln
をハードリンク作成に使うこともないとは思うが)。
注意点
シンボリックリンクの作成権限
- 【WSL 2互換性チェック】NTFSのシンボリックリンクやジャンクションは使い物になるのか?:Windows 10 The Latest - @IT
- 「Windows 10 Creators Update」では管理者権限なしでシンボリックリンクを作成可能に - 窓の杜
オプション未指定、または /d
でシンボリックリンクを作成する場合、デフォルトでは権限がないため、 この操作を実行するための十分な特権がありません。
というエラーが発生する。
シンボリックリンクを作成するには、コマンドプロンプトを管理者権限で実行して実行するか、開発者モードを有効とする必要がある模様。
開発者モードを有効化するには、Windows10の「設定」>「更新とセキュリティ」>「開発者向け」から「開発者モード」を選択し、再起動する。
コマンドプロンプトからしか実行できない
PowerShellや、Git for Windowsに付属するGit Bashから実行しようとしても、エラーとなる。
PS C:\Users\hepokon365> mklink
mklink : 用語 'mklink' は、コマンドレット、関数、スクリプト ファイル、または操作可能なプログラムの名前として認識されま
せん。名前が正しく記述されていることを確認し、パスが含まれている場合はそのパスが正しいことを確認してから、再試行してく
ださい。
exeにパスを通そうと思って where mklink
しても、ファイルパスが見つからない。
C:\Users\hepokon365>where mklink 情報: 与えられたパターンのファイルが見つかりませんでした。
どうやら、 cmd.exe
の組み込みコマンドの模様。
例えばPowerShellから実行する場合、 Start-Process cmd "/c mklink ..."
でコマンドプロンプトを起動し、コマンドとして渡してやればいい。この時、 -Verb Runas
オプションを使用すれば、管理者権限でコマンドプロンプトの実行が可能。
Start-Process -Verb Runas cmd "/c mklink /d <link> <target>"
なお、Git Bashでは ln
が使えるが、 -s
オプション付きで実行しても、ファイルコピーが行われるだけの模様。
振り返り
シンボリックリンクが作れるとはいえ、管理者権限または開発者モードを有効にしないと使えなかったりと制限が多い。
ディレクトリのシンボリックリンクを作る用途で、かつ作成後にターゲットディレクトリを移動することがないのであれば、 /j
によるディレクトリジャンクションリンクが権限不要で同じように使えるため、そちらを検討してもよさそう。