在PowerShell中创建指向文本文件的可点击链接
我想在将要在Windows终端中运行的PowerShell脚本里,为一个文本文件创建一个超链接。我已经通过硬编码链接让它工作,例如 file://c:/textfile.txt,但我想从变量来构建它,至于如何把反斜杠改成正斜杠,我还没想清楚。
Here's what I've tried:
$CurrentFolder = (Get-Location).Path
$settingsFile = "textfile.txt"
$settings = Join-Path $currentFolder $settingsFile
$settingsLink = "file://$settings"
That produces this, which doesn't work: file://C:\textfile.txt
解决方案
字符串替换可以使用 -replace $regex, $subst 运算符,或者使用 .Replace($string, $subst) 方法来完成。前者需要正则表达式(因此输入中的反斜杠需要转义),后者则是普通字符串。
$withslashes = $path -replace "\\", "/"
$withslashes = $path.Replace("\", "/")
别忘了对路径进行URL编码——这是包含特殊字符的路径所必需的:
$url = "file:///" + [uri]::EscapeUriString(($path -replace "\\", "/"))
$url = "file:///" + [uri]::EscapeUriString($path.Replace("\", "/"))
在这种情况下,EscapeUriString 会原样保留 : 和 /,因此可以一次性传递整个路径。
如果没有这样做,你仍然可以将每个路径组件分别进行编码(在其他编程语言中这可能是必要的):
"file:///" + (($path -split "\\" | % {[uri]::EscapeUriString($_)}) -join "/")
注意URL语法是 scheme: //host /path。对于 file: 类型的URL,主机名应留空,但仍然需要正确数量的斜杠——总共三条;两条表示后面的主机名为空,另一条表示路径跟随。
file:///C:/foo/bar
带主机名的示例以说明语法(一般不允许带主机名的文件URL,但在某些特殊情况下会用到,比如终端中的OSC 7 “当前路径” 指示):
file://desktop-asdfgh/C:/foo/bar
从语法上讲,完整省略 //host 部分、只保留一个斜杠来表示后面的 /path 跟随也是成立的——这在Windows Terminal中被识别,在KDE中也常见:
file:/C:/foo/bar
但如果你写成 file://C:/foo/bar,那就意味着 C: 是主机名。某些程序会无论如何都能理解,但有些不会——Windows Terminal就不会。
你可以使用OSC 8序列来创建带自定义文本的链接(Windows Terminal及其他若干终端都支持):
$ESC = [char] 0x1B
echo ("$ESC]8;;" + $url + "$ESC\" + "Hello" + "$ESC]8;;" + "$ESC\")
$ESC + "[" 是CSI,$ESC + "]" 是OSC,$ESC + "\" 是ST(序列结束符)。