◆ ジャンクションをコマンドで作るのが面倒
◆ ショートカットをマウスで作ってジャンクションに置き換えれるように

ジャンクション(シンボリックリンク)を作りたいことはときどきあるのですが そのたびにコマンドプロンプトを開いてパス入力は面倒です
しかも Windows と Linux でコマンドが似てるようで違うので覚えづらいです

それに比べてショートカットは右クリックでドラッグアンドドロップしてショートカットの作成を選ぶだけなので手軽です
ショートカットの lnk ファイルを開けば Windows がリンク先のファイルやアプリケーションを起動してくれるのでこれで済むこともあります

しかし リンク先フォルダの中のこのファイルみたいなのはショートカットではできません
ショートカットはフォルダじゃなくてあくまでファイルという扱いです
lnk ファイルを引数に渡しても lnk ファイルのまま受け取ります

どうにかしたいなーと思った結果 ショートカットをジャンクション置き換える物を作りました
ショートカットは普通にマウス操作で作って そのあとでショートカットをジャンクションに置き換えます

[link.js]
var sh = WScript.CreateObject("WScript.Shell")
var fso = WScript.CreateObject("Scripting.FileSystemObject")

var link = WScript.Arguments.Item(0)
var shortcut = sh.CreateShortcut(link)
var target = shortcut.TargetPath

if (!target) {
WScript.Echo("リンク先がみつかりません")
WScript.Quit(1)
}

var type = fso.FolderExists(target) ? "junction"
: fso.FileExists(target) ? "symlink"
: null

if (!type) {
WScript.Echo("リンク先がみつかりません")
WScript.Quit(1)
}

var newlink = link.replace(/\.lnk$/, "")

if (fso.FileExists(newlink)) {
WScript.Echo("すでにリンク名のファイルが存在します")
WScript.Quit(1)
}

var values = { option: { junction: "/J", symlink: "", symlinkd: "/D"}[type], link: newlink, target: target }
var command = 'cmd /c mklink {{ option }} "{{ link }}" "{{ target }}"'.replace(/\{\{ *([a-z]+) *\}\}/g, function (_, name) { return values[name] })

sh.Exec(command)

[link.bat]
wscript "%~dp0link.js" %*

もともと C# や Python でやろうとしてたのですが ショートカットの情報取得やジャンクション作成が簡単じゃなくて結局 WSH shell 使ったりしてたので最初から wsh の jscript ですることにしました

lnk ファイルを bat ファイルへドロップするかコマンドプロンプトで引数として渡せば使えます
コマンドプロンプト出してしまうのだと最初から mklink コマンドでいいや感もあるのでマウス操作だけでできるドロップのほうがおすすめです

できれば lnk ファイルを右クリックしたメニューからできるようにしたいのですが そこまでやると最初から右クリックのドラッグアンドドロップで「ショートカットの作成」を選ぶ代わりに「ジャンクションの作成」を選べるようにすれば良い気もしてきます
ただ 右クリックメニュー拡張になるとレジストリ操作とか面倒なことになってくるので気楽に使える bat ファイルでショートカットをジャンクションに置き換えということにしてます

一応シンボリックリンクにも対応していて ファイルの場合はジャンクションを作れないのでシンボリックリンクを作るようになってます
ただし シンボリックリンクはデフォルトだと権限がいるので 管理者以外で実行したり権限なしでシンボリックリンクを作れる開発者モードが有効じゃないとエラーになって動きません