【bat】mklink コマンド完全ガイド|シンボリックリンク・ジャンクション・ハードリンクの作成・削除・確認・使い分けまで

【bat】mklink コマンド完全ガイド|シンボリックリンク・ジャンクション・ハードリンクの作成・削除・確認・使い分けまで bat

シンボリックリンクは「実体は別の場所にあるが、見かけ上は指定した場所にあるように見えるエイリアス」です。設定ファイルを複数プロジェクトで共有したり、パス長問題を回避したり、ディスクを節約しながらファイルを「コピー」したように見せたりと、使いこなすと作業効率が上がります。

Windows では mklink コマンドでシンボリックリンク・ジャンクション・ハードリンクを作成できます。この記事では4種類のリンクの違いを整理したうえで、バッチファイルからの自動化パターンまで一通り解説します。

スポンサーリンク

mklink コマンドの基本構文と4種類のリンク

基本構文
mklink [オプション] リンク名 ターゲット

オプションなし  : ファイルへのシンボリックリンク
/D             : ディレクトリへのシンボリックリンク
/H             : ハードリンク(ファイルのみ)
/J             : ジャンクション(ディレクトリのみ)

引数の順番は「リンク名(作りたいパス)→ ターゲット(実体のパス)」です。コピーコマンドと逆になるので最初は戸惑いやすい点です。

4種類のリンク比較表

種類 対象 クロスドライブ 管理者権限 相対パス 主な用途
ファイルシンボリックリンク ファイル 通常は必要 設定ファイルの共有
ディレクトリシンボリックリンク(/D) ディレクトリ 通常は必要 フォルダエイリアス・デプロイ先切り替え
ジャンクション(/J) ディレクトリ ローカルのみ 不要 ×(絶対パスのみ) フォルダの別名・旧パス互換
ハードリンク(/H) ファイル ×(同ボリュームのみ) 不要 ファイルの複数エントリ・バックアップ

迷ったらジャンクション(/J)が無難です。管理者権限が不要で、ディレクトリへのリンクを同一ドライブ内で作れます。ドライブをまたぐ場合やネットワークパスに対応したい場合はシンボリックリンク(/D)を使います。

ファイルシンボリックリンクを作成する

ファイルへのシンボリックリンクを作成します。リンクはオリジナルと同じように読み書きでき、削除してもオリジナルには影響しません。

ファイルシンボリックリンク作成.bat
@echo off
rem mklink リンク名 ターゲット(絶対パス推奨)
mklink "C:\work\config.ini" "D:\shared\config.ini"
if ERRORLEVEL 1 (
    echo [ERROR] シンボリックリンクの作成に失敗しました。
    echo 管理者権限で実行しているか確認してください。
) else (
    echo [OK] シンボリックリンクを作成しました。
)

ディレクトリシンボリックリンクを作成する(/D)

ディレクトリへのシンボリックリンクです。フォルダのエイリアスを作ったり、デプロイ先を切り替えたりするのに使います。ネットワークパスを対象にすることも可能です。

ディレクトリシンボリックリンク作成.bat
@echo off
rem /D でディレクトリへのシンボリックリンク
mklink /D "C:\app\config" "D:\shared\app-config"
if ERRORLEVEL 1 (
    echo [ERROR] 作成に失敗しました。管理者権限を確認してください。
) else (
    echo [OK] ディレクトリシンボリックリンクを作成しました。
)

ジャンクションを作成する(/J)

ジャンクションは管理者権限なしで作れるディレクトリへのリンクです。同一ボリューム内ならパス長問題の回避にも使えます。パス長制限の最終手段集でも紹介しています。

ジャンクション作成.bat
@echo off
rem /J でジャンクション(管理者権限不要・絶対パスのみ)
mklink /J "C:\short" "C:\very\long\path\to\project\folder"
echo ジャンクションを作成しました。

ジャンクションは 絶対パスのみ対応です。相対パスを指定しても自動的に絶対パスに変換されます。また、ネットワークパス(\\server\share)は対象にできません(その場合はシンボリックリンク /D を使う)。

ハードリンクを作成する(/H)

ハードリンクはファイルの「別名」です。同じファイルデータを指す複数のエントリを作れます。どちらから変更しても同期され、片方を削除してももう一方は残ります。

ハードリンク作成.bat
@echo off
rem /H でハードリンク(同一ボリューム内のファイルのみ)
mklink /H "C:\backup\report.xlsx" "C:\work\report.xlsx"
echo ハードリンクを作成しました。

ハードリンクの注意点:同一ボリューム(ドライブ)内のファイルのみ対象です。ディレクトリには使えません。ファイルを「削除」しても、ハードリンクが残っているかぎりデータは消えません。fsutil hardlink list ファイル名 で同一データを参照しているすべてのパスを確認できます。

リンクの存在確認・種類を調べる

作成したリンクの種類は dirfsutil で確認できます。

リンク種類の確認
rem dir コマンドでリパースポイントのみを一覧表示
dir /AL "C:\work"

rem fsutil でシンボリックリンク情報を確認
fsutil reparsepoint query "C:\app\config"

rem ハードリンク数を確認(2以上でハードリンクあり)
fsutil hardlink list "C:\work\report.xlsx"

dir /AL の出力例:

dir /AL の出力例
2024/03/01  10:00    <SYMLINKD>     config [D:\shared\app-config]
2024/03/01  10:01    <JUNCTION>      short [C:\very\long\path\...]
2024/03/01  10:02    <SYMLINK>      config.ini [D:\shared\config.ini]

バッチファイルからリンクかどうかを判定するには dir の出力を findstr でフィルタリングします。

リンク種類をバッチで判定.bat
@echo off
set TARGET=C:\app\config

dir /AL "%TARGET%" 2>nul | findstr /i "<JUNCTION>" >nul
if %ERRORLEVEL%==0 (
    echo %TARGET% はジャンクションです。
    exit /b 0
)

dir /AL "%TARGET%" 2>nul | findstr /i "<SYMLINKD>" >nul
if %ERRORLEVEL%==0 (
    echo %TARGET% はディレクトリシンボリックリンクです。
    exit /b 0
)

echo %TARGET% は通常のディレクトリです。

リンクの存在チェックと条件分岐

IF EXIST による存在確認はリンク自体の存在チェックに使えます。ただし、リンク先のファイル・フォルダが存在しない「壊れたリンク」でも IF EXIST はリンク自体を検出します。

リンク存在チェック&作成.bat
@echo off
set LINK=C:\app\config
set TARGET=D:\shared\app-config

rem リンク(またはフォルダ)の存在チェック
if exist "%LINK%\" (
    echo リンクまたはフォルダが既に存在します。スキップします。
) else (
    echo 存在しません。ジャンクションを作成します。
    mklink /J "%LINK%" "%TARGET%"
    if ERRORLEVEL 1 (
        echo [ERROR] 作成に失敗しました。
        exit /b 1
    )
    echo [OK] ジャンクションを作成しました。
)

リンクを削除する

シンボリックリンクやジャンクションの削除には 通常の rmdir / del を使います。リンク自体が削除されるだけで、リンク先のデータは消えません。

リンクの削除
rem ディレクトリシンボリックリンク・ジャンクションの削除
rem ★ /s を付けると リンク先も再帰削除される危険あり ★
rmdir "C:\app\config"

rem ファイルシンボリックリンク・ハードリンクの削除
del "C:\work\config.ini"

要注意:rmdir /s は使わないこと
ジャンクションやディレクトリシンボリックリンクに対して rmdir /s を実行すると、リンク先フォルダの中身まで再帰的に削除されます。必ず rmdir リンク名(/s なし)でリンク自体のみを削除してください。

リンクをまとめて削除.bat
@echo off
rem 複数のジャンクション・シンボリックリンクを一括削除
for %%L in (
    "C:\app\config"
    "C:\app\logs"
    "C:\app\data"
) do (
    if exist "%%~L\" (
        rmdir "%%~L"
        echo [OK] %%~L を削除しました。
    ) else (
        echo [SKIP] %%~L は存在しません。
    )
)

管理者権限が必要な場合の対処

シンボリックリンク(オプションなし・/D)の作成はデフォルトで管理者権限が必要です。管理者権限の自動取得と組み合わせるか、以下の方法で解決できます。

方法1:管理者権限チェック付きバッチ

管理者権限チェック付きmklink.bat
@echo off
net session >nul 2>&1
if ERRORLEVEL 1 (
    echo [ERROR] このスクリプトは管理者権限が必要です。
    echo 右クリック→「管理者として実行」してください。
    pause
    exit /b 1
)
mklink /D "C:\app\config" "D:\shared\config"
echo [OK] 作成しました。

方法2:Developer Mode でシンボリックリンクを許可(Windows 10/11)

設定アプリ → システム → 開発者向け → 開発者モード を有効にすると、一般ユーザーでもファイル・ディレクトリシンボリックリンクを作成できます。開発マシンではこの設定を入れておくと便利です。

ジャンクション(/J)とハードリンク(/H)は管理者権限不要のため、権限が取れない環境では代替として使えます。

SUBST コマンドとの違い

似た用途に SUBST コマンド(パスに仮想ドライブレターを割り当てる)があります。違いを整理します。

項目 mklink /J SUBST
管理者権限 不要 不要
再起動後 永続(レジストリ不要) 消える(スタートアップに登録が必要)
アクセス方法 フォルダパス ドライブレター(例: X:\)
Explorer での見え方 フォルダ(リンクマーク付き) 仮想ドライブ
タスクスケジューラからのアクセス △(別セッションでは見えないことがある)

再起動しても消えない永続的なパスエイリアスが欲しい場合は mklink /J が適しています。短いドライブレターで参照したい場合や一時的な用途には SUBST が手軽です。

相対パスでシンボリックリンクを作成する

シンボリックリンクは相対パスで作成できます。ただし、相対パスはリンクが存在する場所を基準にします。バッチファイルの実行フォルダではない点に注意してください。

相対パスでシンボリックリンク.bat
@echo off
rem カレントディレクトリを移動してから相対パスでリンク作成
pushd "C:\projects\myapp"
mklink /D "configs" "..\..\shared\configs"
popd

rem 相対パスリンクの確認: dir /AL で [..\..\shared\configs] と表示される
dir /AL "C:\projects\myapp\configs"

%~dp0 を使ったパス取得と組み合わせると、バッチファイルの場所を基準にした相対リンクを確実に作れます。

バッチファイル基準の相対シンボリックリンク.bat
@echo off
rem バッチファイルの場所を基準にする
set BAT_DIR=%~dp0

pushd "%BAT_DIR%"
mklink /D "output" "..\build\release"
popd
echo [OK] %BAT_DIR%output → %BAT_DIR%..\build\release

実践パターン集

パターン1:設定ファイルを複数プロジェクトで共有する

同じ設定ファイルを複数プロジェクトで使い回したい場合、コピーして管理すると変更が同期されません。シンボリックリンクなら1か所を更新するだけで全プロジェクトに反映されます。

設定ファイル共有.bat
@echo off
setlocal
set SHARED=D:\shared
set PROJECTS=C:\projects\app1 C:\projects\app2 C:\projects\app3

for %%p in (%PROJECTS%) do (
    rem 既存ファイルがあれば削除してからリンク作成
    if exist "%%p\config.ini" del "%%p\config.ini"
    mklink "%%p\config.ini" "%SHARED%\config.ini"
    echo [OK] %%p\config.ini を共有しました。
)

パターン2:デプロイ先フォルダをジャンクションで切り替える

Blue/Green デプロイやバージョン切り替えに使えます。current というジャンクションが常に最新バージョンを指すようにしておけば、アプリはパスを変えずに最新版を参照できます。

バージョン切り替えデプロイ.bat
@echo off
setlocal
set NEW_VERSION=C:\app\v2.0
set LINK=C:\app\current

rem 古いジャンクションを削除(リンク先は削除しない!rmdir /s は NG)
if exist "%LINK%\" (
    rmdir "%LINK%"
    echo [INFO] 旧バージョンリンクを削除しました。
)

rem 新バージョンへのジャンクション作成
mklink /J "%LINK%" "%NEW_VERSION%"
if ERRORLEVEL 1 (
    echo [ERROR] リンク作成に失敗しました。
    exit /b 1
)
echo [OK] %LINK% → %NEW_VERSION% に切り替えました。

パターン3:パス長制限を回避する

長いパスを持つプロジェクトでビルドや解析ツールがエラーになる場合、ジャンクションで短いパスを作ることで回避できます。詳しくはMAX_PATH 完全攻略を参照してください。

パス長問題の回避.bat
@echo off
rem 長いパスを短いエイリアスにマップ(ジャンクション)
mklink /J "C:\p" "C:\Users\username\Documents\projects\very-long-project-name"

rem これで C:\p\src\main.c のような短いパスでアクセスできる
echo C:\p を短縮パスとして使用できます。
echo 不要になったら rmdir C:\p で削除(/s は付けない)

パターン4:ログ・データフォルダをデータドライブに向ける

アプリがCドライブ固定のパスにログを書く場合、ジャンクションでDドライブのフォルダに向けることでCドライブの圧迫を防げます。

ログフォルダをデータドライブに向ける.bat
@echo off
setlocal
set APP_LOG=C:\app\logs
set DATA_LOG=D:\logs\app

rem データドライブにログフォルダを作成
if not exist "%DATA_LOG%" mkdir "%DATA_LOG%"

rem アプリの logs フォルダをバックアップして削除
if exist "%APP_LOG%\" (
    echo 既存のログフォルダをリネームして退避します...
    ren "%APP_LOG%" "logs_backup"
)

rem ジャンクションで向け直す
mklink /J "%APP_LOG%" "%DATA_LOG%"
echo [OK] %APP_LOG% → %DATA_LOG% にジャンクションを作成しました。

パターン5:一括セットアップスクリプト(作成&削除対応)

リンク一括セットアップ.bat
@echo off
setlocal enabledelayedexpansion

rem 引数: setup(作成)または teardown(削除)
if "%~1"=="teardown" goto TEARDOWN

:SETUP
echo リンクを作成します...
call :make_junction "C:\app\logs"   "D:\logs\app"
call :make_junction "C:\app\data"   "D:\data\app"
call :make_junction "C:\app\config" "D:\shared\config"
echo セットアップ完了。
exit /b 0

:TEARDOWN
echo リンクを削除します...
for %%L in ("C:\app\logs" "C:\app\data" "C:\app\config") do (
    if exist "%%~L\" (
        rmdir "%%~L"
        echo [OK] %%~L を削除しました。
    )
)
echo ティアダウン完了。
exit /b 0

:make_junction
rem %1=リンク名, %2=ターゲット
if exist "%~1\" rmdir "%~1"
mklink /J "%~1" "%~2"
if ERRORLEVEL 1 (
    echo [ERROR] %~1 の作成に失敗しました。
) else (
    echo [OK]    %~1 → %~2
)
exit /b 0

よくあるトラブルと対処法

エラー・症状 原因 対処法
「このコマンドの使い方は正しくありません」 リンク名またはターゲットのパスに誤りがある パスをダブルクォートで囲む。ターゲットは実在するパスを指定する
「アクセスが拒否されました」 シンボリックリンク作成に管理者権限が必要 管理者として実行する。または /J を使う。開発者モードを有効にする
「既にファイルが存在します」 同名のファイル・フォルダ・リンクが既に存在 事前に del または rmdir でリンク/ファイルを削除する
ジャンクションからリンク先ファイルが消えた rmdir /s でジャンクションを削除してしまった 今後は rmdir(/s なし)でリンクのみ削除する。バックアップから復元
dir で SYMLINK/JUNCTION と表示されない dir に /AL オプションを付けていない dir /AL パス で確認する
リンク経由でアクセスできない リンク先が別ドライブで、ジャンクションを使っている クロスドライブにはシンボリックリンク(/D)を使う
robocopy でリンク先の実体がコピーされる robocopy のデフォルト動作がリンク先を辿る robocopy /SL でリンク自体をコピーする
ジャンクションを作ったが再起動後に消えた ジャンクションは消えない。ただしSUBSTは消える dir /AL で確認する。SUBST と混同していないか確認

まとめ

やりたいこと コマンド 権限 特徴
ファイルのシンボリックリンク mklink リンク名 ターゲット 管理者 or Dev Mode クロスドライブ○、相対パス○
フォルダのシンボリックリンク mklink /D リンク名 ターゲット 管理者 or Dev Mode クロスドライブ○、NW○
ジャンクション(権限不要) mklink /J リンク名 ターゲット 不要 ローカルのみ、絶対パスのみ
ハードリンク mklink /H リンク名 ターゲット 不要 同ボリューム・ファイルのみ
リンク一覧を確認 dir /AL パス 不要 SYMLINKD / JUNCTION / SYMLINK
ジャンクション・ディレクトリリンクを削除 rmdir リンク名(/s なし) 不要 /s を付けると実体も削除!
ファイルリンクを削除 del リンク名 不要 実体は残る

権限が取れない環境ではジャンクション(/J)、ドライブをまたぐ場合や相対パスが必要な場合はシンボリックリンク(/D)、ファイルデータを節約しつつ複数のパスから参照したい場合はハードリンク(/H)と使い分けてください。

よくある質問

シンボリックリンクとジャンクションはどう使い分けますか?
ジャンクションは管理者権限不要で使えるため、多くのケースでジャンクション(/J)が手軽です。ただしジャンクションはローカルドライブの絶対パスのみ対応で、ネットワークパスや相対パスには使えません。ドライブをまたぐ場合・相対パスを使いたい場合・ネットワークパスを指定したい場合はシンボリックリンク(/D)を選びます。
リンク先を変更するにはどうすればいいですか?
mklink にはリンク先を変更するオプションがありません。一度リンクを削除してから作り直す必要があります。ジャンクションなら rmdir リンク名(/s なし)、ファイルシンボリックリンクなら del リンク名 で削除してから、mklink で再作成します。
robocopy でシンボリックリンクをコピーするとリンク先がコピーされてしまいます。
robocopy のデフォルトはリンク先の実体をコピーします。リンク自体をコピーしたい場合は /SL オプションを付けてください。xcopy には同等のオプションがなく、常にリンク先の実体がコピーされます。
バッチファイルから mklink を実行しても何も起きません。
シンボリックリンクの作成に失敗していても ERRORLEVEL が確認しづらいことがあります。エラーメッセージを確認するために 2>&1 でエラー出力をリダイレクトしてみてください。また、管理者権限が必要なケースで権限がない場合は「アクセスが拒否されました」のエラーが出ます。
Git リポジトリでシンボリックリンクを使うと問題がありますか?
Git for Windows はデフォルトでシンボリックリンクを通常ファイルとして扱います。シンボリックリンクをリポジトリで管理したい場合は、Git の設定で core.symlinks=true を有効にしてから管理者権限でクローンする必要があります。チームで共有する場合は全員の環境設定が必要になるため、ジャンクションをリポジトリ外で管理する方が運用しやすいことが多いです。
ジャンクションはSUBSTと何が違いますか?
SUBST はパスに仮想ドライブレター(X:\ など)を割り当てます。再起動すると消えるため、スタートアップに登録するか毎回実行が必要です。一方ジャンクションはファイルシステム上のリンクなので、再起動しても消えません。また SUBST はタスクスケジューラや別セッションからアクセスできないことがありますが、ジャンクションはその問題がありません。永続的なパスエイリアスにはジャンクションが適しています。