当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] 周五乐趣:PowerShell 控制台编辑

作者:精品下载站 日期:2024-12-14 08:04:46 浏览:14 分类:玩电脑

周五乐趣:PowerShell 控制台编辑


有一天,我在 Adam Bertram 的博客上读到一篇有趣的文章,内容是关于在 PowerShell 中使用文本编辑器编辑文件。很自然地,我脑子里的 PowerShell 轮子开始转动。虽然我对文章中的一些选项很感兴趣,但实际上我已经安装了 Micro 编辑器来使用,我意识到我已经安装了我最喜欢的控制台文本编辑器。文章提到安装适用于 Windows 的 Nano 编辑器。但我有 Ubuntu 的 WSL 安装。我已经有了 Nano 编辑器。公平地说,我安装了 Windows 版 Nano,但它与 Linux 版本的不同足以让我烦恼。为什么不让我更轻松地使用 PowerShell 控制台中已有的内容呢?让我们玩得开心,也许还能学到一些新东西。

WSL 命令

如果您安装了 Linux 发行版,则可以从 PowerShell 提示符运行本机 Linux 命令。

[玩转系统] 周五乐趣:PowerShell 控制台编辑

通常,这些命令在 Linux shell 中运行,但我在 PowerShell 控制台中获取输出。无论如何,我可以直接从 PowerShell 提示符轻松启动 Nano 编辑器。

wsl nano

转换路径

但这就是棘手的地方。我希望能够启动 Nano 编辑器并从 Windows 打开文本文件。在 Linux 中,我可以运行这样的命令:

nano /home/jeff/file.txt

如果我在 PowerShell 提示符下尝试类似的操作:

wsl nano c:\work\fun.ps1

纳米编辑器将打开,但认为我正在创建一个新文件。这是因为 nano 确实在 Ubuntu 发行版中运行,而不是在我的 PowerShell 提示符中运行。幸运的是,我的所有本地驱动器都自动安装在 WSL 中。如果我在脑海中转换路径,这就会起作用。

wsl nano /mnt/c/work/fun.ps1

当然,我希望事情简单易行,因此我需要一个函数将 Windows 路径转换为 WSL 安装路径。首先,我应该将 Windows 路径转换为真实的文件系统路径。这将有助于转换 .\file.txt 等路径或我使用 S:\remote.ps1 等 PSDrive 的路径。

$cPath = Convert-Path -Path $Path

然后,我将把转换后的路径拆分为父目录和文件名。

$file = Split-Path -Path $cpath -Leaf
$dir = Split-Path -Path $cPath -Parent

接下来,我想要父目录的路径部分,不带驱动器号。

$folder = $dir.Substring(3)

我这样做是因为我需要使用挂载点在Linux中构建相应的路径。

"/mnt/{0}/{1}/{2}" -f $dir[0].tostring().ToLower(), $folder.replace("\", "/"), $file

我正在使用父目录的第一个字母构建一个新字符串。因为 Linux 区分大小写,所以我将其转换为小写以匹配 Linux 中的路径。我必须做的另一个调整是将所有\切换为 /。

[玩转系统] 周五乐趣:PowerShell 控制台编辑

现在 nano 命令可以按预期工作。

[玩转系统] 周五乐趣:PowerShell 控制台编辑

构建工具集

当然,考虑到我是否想编辑现有文件或创建新文件,我还构建了一个 PowerShell 函数来启动 nano。

[string]$cmd = "wsl --exec nano"
if ($Path) {
    $wslPath = ConvertTo-WSLPath -Path $Path
    $cmd += " $wslPath"

}
#convert to a scriptblock
$sb = [scriptblock]::Create($cmd)
Invoke-Command -ScriptBlock $sb

这是该函数的核心。

我添加的最后一部分与验证相关。我的 ConvertTo-WSLPath 和 Invoke-Nano 函数位于 .ps1 文件中,我必须点源该文件。但如果没有安装WSL则无法使用这些命令

$WslTest = ((wsl -l).split()).where({$_.length -gt 1}) -contains "(Default)"
If ( -Not $WslTest) {
    Write-Warning "These commands require a WSL installation"
    Return
}

弄清楚这一点比我想象的要付出更多的努力。您可以运行 wsl -l 来查看已安装的安装。但是,输出的编码不一定是您在控制台中看到的编码。我使用 -Match 或 Select-String 的努力一直失败。最终,我想出了这段代码,将 wsl 命令的结果拆分为长度大于 1 的字符串数组。然后我可以使用 -Contains 查找“(Default)”。如果找不到该字符串,我将显示警告,然后退出脚本。

我还想验证点源脚本是否在 Windows(PowerShell 7 或 Windows PowerShell)中运行。我的函数是在 If 语句内定义的。

if ($IsWindows -OR ($PSEdition -eq 'desktop')) {
 #define functions
}
Else {
    Write-Warning "These commands require a Windows platform"
}

如果 PowerShell 控制台是其他任何内容,则会显示另一个警告。想看看最终结果吗?

# requires -version 5.1

#launch the nono text editor from a WSL installation like Ubuntu
# or install the Windows version https://sourceforge.net/projects/nano-for-windows/
# or https://sourceforge.net/projects/micro-for-windows/
# https://micro-editor.github.io/

if ($IsWindows -OR ($PSEdition -eq 'desktop')) {

    #test if there is a default WSL installation
    $WslTest = ((wsl -l).split()).where({$_.length -gt 1}) -contains "(Default)"
    If ( -Not $WslTest) {
        Write-Warning "These commands require a WSL installation"
        Return
    }

    # a helper function to convert a Windows path to the WSL equivalent
    Function ConvertTo-WSLPath {
        [cmdletbinding()]
        [outputtype("String")]

        Param(
            [Parameter(Position = 0, Mandatory, HelpMessage = "Enter a Windows file system path")]
            [ValidateNotNullorEmpty()]
            [string]$Path
        )

        Write-Verbose "[$($myinvocation.mycommand)] Starting $($myinvocation.mycommand)"
        Write-Verbose "[$($myinvocation.mycommand)] Converting $Path to a filesystem path"
        $cPath = Convert-Path -Path $Path
        Write-Verbose "[$($myinvocation.mycommand)] Converted to $cpath"

        $file = Split-Path -Path $cpath -Leaf
        $dir = Split-Path -Path $cPath -Parent
        $folder = $dir.Substring(3)
        "/mnt/{0}/{1}/{2}" -f $dir[0].tostring().ToLower(), $folder.replace("\", "/"), $file

        Write-Verbose "[$($myinvocation.mycommand)] Ending $($myinvocation.mycommand)"
    }

    #launch the nano editor from the WSL installation
    Function Invoke-Nano {
        [CmdletBinding()]
        [outputtype("none")]
        [alias("nano")]

        Param(
            [Parameter(Position = 0, HelpMessage = "Specify a text file path.")]
            [ValidatenotNullorEmpty()]
            [ValidateScript({ Test-Path $_ })]
            [string]$Path
        )
        Write-Verbose "[$($myinvocation.mycommand)] Starting $($myinvocation.mycommand)"
        [string]$cmd = "wsl --exec nano"
        if ($Path) {
            Write-Verbose "[$($myinvocation.mycommand)] Convert $Path"
            $wslPath = ConvertTo-WSLPath -Path $Path
            $cmd += " $wslPath"

        }
        Write-Verbose "[$($myinvocation.mycommand)] Using command expression $cmd"
        #convert to a scriptblock
        $sb = [scriptblock]::Create($cmd)

        Write-Verbose "[$($myinvocation.mycommand)] Launch nano from the WSL installation"
        Invoke-Command -ScriptBlock $sb
        Write-Verbose "[$($myinvocation.mycommand)] Ending $($myinvocation.mycommand)"
    }
}
Else {
    Write-Warning "These commands require a Windows platform"
}

我想通过我的详细陈述指出一些新的东西。我经常有函数调用其他函数。在每个详细语句中,我都包含命令名称。这使得跟踪流量变得更加容易。

[玩转系统] 周五乐趣:PowerShell 控制台编辑

现在,我可以直接从 PowerShell 控制台快速编辑文件。

[玩转系统] 周五乐趣:PowerShell 控制台编辑

不,这不会取代我使用 VS Code 或 PowerShell ISE 获得的功能。但有时我只想快速编辑或查看源代码。我偏爱 nano 编辑器,但您可以使用这些概念来启动 vim 或在 WSL 安装中安装的任何其他文本编辑器。

玩得开心。

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯