2025/10/19(日)PowerShellでワイルドカード文字 [ ] を含むパスへのリンクをNew-Itemで作れない問題が修正される予定

PowerShellのワイルドカード文字 [ ] 問題

PowerShellの多くのコマンドレットは [ ] を含んだパスをワイルドカードと解釈します。

Get-Item -Path "[abc].txt"

Name
----
a.txt
b.txt
c.txt

たいていの場合これは望んでいない動作なので、ワイルドカード処理を行わない-LiteralPathを使うことがPowerShellではほぼ必須です。(あまりに残念な失敗仕様……。)

Get-Item -LiteralPath "[abc].txt"

Name
----
[abc].txt

New-Itemでのリンク作成時のワイルドカード文字問題

New-Itemでのリンク作成時の -Target (または -Value) にも同様の問題があります。厄介なことに、-LiteralPathのようなワイルドカード処理を無効化する手段がありません。

New-Item -ItemType SymbolicLink -Path "link.txt" -Target "[abc].txt"

Name
----
link.txt -> a.txt

一応、バッククォート(`)で二重エスケープすれば作れなくもありません。

New-Item -ItemType SymbolicLink -Path "link.txt" -Target "````[abc````].txt"

Name
----
link.txt -> [abc].txt

パスが変数とかに入っている場合はエスケープする関数とかを作るか[WildcardPattern]::Escapeを2回使えば同じ効果。

New-Item -ItemType SymbolicLink -Path "link.txt" -Target ([WildcardPattern]::Escape([WildcardPattern]::Escape("[abc].txt")))

ただし、この方法でも中間パスに [ ] が含まれている場合は失敗します。

New-Item -ItemType SymbolicLink -Path "link.txt" -Target ([WildcardPattern]::Escape([WildcardPattern]::Escape("[xyz]\1\2.txt")))
New-Item: Cannot find path '``[xyz``]\1\2.txt' because it does not exist.
Test-Path -LiteralPath "[xyz]\1\2.txt"
True

結局、一番確実なのは、残念なことに以下の方法です。

& cmd "/c" mklink "link.txt" "[xyz]\1\2.txt"

v7.6.0で修正予定

この問題はIssueに挙がっていて、割と最近TargetをLiteral扱いする修正が入ることになったようです。

v7.6.0-preview.5 Releaseで試したところ直っていました。たぶん次の正式リリース時には修正されそうです。

New-Item -ItemType SymbolicLink -Path "link.txt" -Target "[xyz]\1\2.txt"

Name
----
link.txt -> [xyz]\1\2.txt

2017/04/08(土)ドライブ空き容量をチェックしてトースト通知する

ドライブ空き容量をチェックしてトースト通知する

PowerShellで空き容量チェックスクリプトを書いてみました。Windows 10 のアクションセンターで通知されます(トースト通知)。

check_diskspace.png

ソースコード

# ドライブごとにしきい値を設定
$min_freespace = @{
    "C" = 30GB;
    "D" = 10GB;
    "E" = 50GB;
}

function ShowBalloonTip(
    [string] $tilte = "件名", 
    [string] $body = "本文"
) {
    #[Reference]
    # PowerShell can I use balloons, toasts and notifications?
    #   https://deploywindows.info/2015/12/01/powershell-can-i-use-balloons-toasts-and-notifications/
    # Toasts templates
    #   https://msdn.microsoft.com/en-us/library/windows/apps/hh761494.aspx

    [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] > $null
    $template = [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent([Windows.UI.Notifications.ToastTemplateType]::ToastText02)
    # Convert to .NET type for XML manipuration
    $toastXml = [xml] $template.GetXml()
    # Customize the toast message
    $text = $toastXml.GetElementsByTagName("text")
    $text[0].AppendChild($toastXml.CreateTextNode($tilte)) > $null
    $text[1].AppendChild($toastXml.CreateTextNode($body)) > $null

    # Convert back to WinRT type
    $xml = New-Object Windows.Data.Xml.Dom.XmlDocument
    $xml.LoadXml($toastXml.OuterXml)
    $Toast = [Windows.UI.Notifications.ToastNotification]::new($xml)

    $AppID = 'Microsoft.Explorer.Notification.{3e1c1f24-a023-49cf-98ff-90cdabb9930b}'

    [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($AppID).Show($Toast)
}

$msg = ""
foreach ($drive_letter in $min_freespace.Keys) {
    $drive = Get-PSDrive $drive_letter
    if ( $drive.Free -lt $min_freespace[$drive_letter] ) {
        $msg += "{0}ドライブ空き容量:{1,0:0.00}GB`n" -f $drive_letter, ($drive.Free/1GB);
    }
}

if ( $msg ) { 
    ShowBalloonTip "空き容量警告" $msg
}

準備

以下のレジストリを登録しないとトースト通知を履歴に残せないようです。(通知自体はされる。)

  • HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Notifications\Settings\Microsoft.Explorer.Notification.3e1c1f24-a023-49cf-98ff-90cdabb9930b
    • 値の名前: ShowInActionCenter
    • 値のデータ: 1
    • 種類: REG_DWORD

コマンドで追加するなら、

reg add "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Notifications\Settings\Microsoft.Explorer.Notification.{3e1c1f24-a023-49cf-98ff-90cdabb9930b}" /v ShowInActionCenter /t REG_DWORD /d 1

「Microsoft.Explorer.Notification.3e1c1f24-a023-49cf-98ff-90cdabb9930b」*1のところに特に意味は無く、ソースコード内のIDと一致していれば良いです。

自動実行

タスクスケジューラーに登録すれば、自動実行できます。

  • プリグラム/スクリプト: %SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe
  • 引数の追加(オプション): -ExecutionPolicy RemoteSigned -File スクリプトのパス

ただ、普通に登録するだけではどうしてもウィンドウが表示されてしまうようです。検索するとWSH(VBScriptやJScript)経由でPowerShellを呼び出すことでウィンドウを隠す方法が見つかります。PowerShell単体でできるようにして欲しい(-_-;)

更新履歴

  • 2017/04/08: 不要な記述が残っていたので削除。

*1 : 3e1c1f24-a023-49cf-98ff-90cdabb9930bは[Guid]::NewGuid()で新規取得したGUIDを使っただけ。