主持人 > 博客 > 管理 > 使用 PowerShell 和 WSL 将 Linux 命令集成到 Windows 中
使用 PowerShell 和 WSL 将 Linux 命令集成到 Windows 中
Windows 开发人员的一个典型问题是:“为什么仍然没有 <ВСТАВЬТЕ ТУТ ЛЮБИМУЮ КОМАНДУ LINUX>?。 无论是强力的滑动 less 或者熟悉的工具 grep или sed,Windows 开发人员希望在日常工作中轻松访问这些命令。
适用于 Linux 的 Windows 子系统 (WSL) 在这方面取得了巨大的进步。 它允许您通过代理从 Windows 调用 Linux 命令 wsl.exe (例如, wsl ls)。 尽管这是一个显着的改进,但该选项存在许多缺点。
无处不在的添加 wsl 乏味且不自然。
参数中的 Windows 路径并不总是有效,因为反斜杠被解释为转义字符而不是目录分隔符。
参数中的 Windows 路径不会转换为 WSL 中相应的挂载点。
具有别名和环境变量的 WSL 配置文件不遵循默认设置。
不支持 Linux 路径补全。
不支持命令完成。
不支持参数完成。
因此,Linux 命令在 Windows 下被视为二等公民,并且比本机命令更难使用。 要实现权利平等,就必须解决所列问题。
PowerShell 函数包装器
使用 PowerShell 函数包装器,我们可以添加命令完成并消除对前缀的需要 wsl,将 Windows 路径转换为 WSL 路径。 对外壳的基本要求:
对于每一个 Linux 命令,都必须有一个同名的函数包装器。
shell 必须识别作为参数传递的 Windows 路径并将其转换为 WSL 路径。
shell 应该调用 wsl 使用适当的 Linux 命令连接到任何管道输入,并将任何命令行参数传递给函数。
由于此模式可以应用于任何命令,因此我们可以抽象这些包装器的定义,并从要导入的命令列表动态生成它们。
# The commands to import.
$commands = "awk", "emacs", "grep", "head", "less", "ls", "man", "sed", "seq", "ssh", "tail", "vim"
# Register a function for each command.
$commands | ForEach-Object { Invoke-Expression @"
Remove-Alias $_ -Force -ErrorAction Ignore
function global:$_() {
for (`$i = 0; `$i -lt `$args.Count; `$i++) {
# If a path is absolute with a qualifier (e.g. C:), run it through wslpath to map it to the appropriate mount point.
if (Split-Path `$args[`$i] -IsAbsolute -ErrorAction Ignore) {
`$args[`$i] = Format-WslArgument (wsl.exe wslpath (`$args[`$i] -replace "", "/"))
# If a path is relative, the current working directory will be translated to an appropriate mount point, so just format it.
} elseif (Test-Path `$args[`$i] -ErrorAction Ignore) {
`$args[`$i] = Format-WslArgument (`$args[`$i] -replace "", "/")
}
}
if (`$input.MoveNext()) {
`$input.Reset()
`$input | wsl.exe $_ (`$args -split ' ')
} else {
wsl.exe $_ (`$args -split ' ')
}
}
"@
}
该函数迭代命令行参数,使用命令确定 Windows 路径 Split-Path и Test-Path然后将这些路径转换为 WSL 路径。 我们通过辅助函数运行路径 Format-WslArgument,我们稍后会定义。 它转义特殊字符,例如空格和括号,否则会被误解。
最后,我们传达 wsl 管道输入和任何命令行参数。
使用这些包装器,您可以以更自然的方式调用您最喜欢的 Linux 命令,而无需添加前缀 wsl 并且不用担心路径如何转换:
man bash
less -i $profile.CurrentUserAllHosts
ls -Al C:Windows | less
grep -Ein error *.log
tail -f *.log
此处显示了基本命令集,但您只需将任何 Linux 命令添加到列表中即可为任何 Linux 命令创建 shell。 如果您将此代码添加到您的 轮廓 PowerShell,这些命令将在每个 PowerShell 会话中可供您使用,就像本机命令一样!
默认设置
在 Linux 中,通常在登录配置文件中定义别名和/或环境变量,为常用命令设置默认参数(例如, alias ls=ls -AFh или export LESS=-i)。 通过非交互式 shell 进行代理的缺点之一 wsl.exe - 配置文件未加载,因此默认情况下这些选项不可用(即 ls 在 WSL 和 wsl ls 与上面定义的别名的行为会有所不同)。
PowerShell 提供 $PSDefaultParameterValues,一种用于定义默认参数的标准机制,但仅适用于 cmdlet 和高级函数。 当然,我们可以在 shell 中创建高级函数,但这会带来不必要的复杂性(例如,PowerShell 会关联部分参数名称(例如, -a 相关于 -ArgumentList),这会与采用部分名称作为参数的 Linux 命令冲突),并且定义默认值的语法将不是最合适的(默认参数需要键中参数的名称,而不仅仅是命令名称) 。
但是,通过对 shell 进行轻微修改,我们可以实现类似于以下的模型 $PSDefaultParameterValues,并启用 Linux 命令的默认选项!
另外,由于我们现在有了 bash 自动补全功能,您可以直接在 PowerShell 中自动补全 Linux 路径!
less /etc/<TAB>
ls /usr/share/<TAB>
vim ~/.bash<TAB>
如果 bash 自动补全未产生任何结果,PowerShell 将恢复为系统默认 Windows 路径。 因此,在实践中,您可以自行决定同时使用这两条路径。
结论
使用 PowerShell 和 WSL,我们可以将 Linux 命令作为本机应用程序集成到 Windows 中。 无需搜索 Win32 版本或 Linux 实用程序,也无需通过转至 Linux shell 来中断您的工作流程。 只是 安装 WSL, 配置 PowerShell 简介 и 列出您要导入的命令! Linux 和 Windows 命令参数和文件路径的丰富自动补全功能甚至在当今的本机 Windows 命令中也不可用。