[英]PowerShell 'less' tool
这不是围绕此的各种其他问题的重复(我审查了它们,但在我看到的问题中没有回答)。 那些其他问题围绕着Out-Host -Paging
more
(即使他们在问题标题中提到的less
)。
为了关注这一特定点,有谁知道复制less
功能的 PowerShell 方法,但在 Microsoft Windows 环境中? 即让我们能够向下和向上滚动文档(使用光标键逐行或使用 PgUp / PgDn 键逐页滚动)以查看帮助和其他文件(例如,我们可以执行Get-Help Get-ChildItem -Full | less
)。
这将非常有用。 我不是在寻找适用于 Windows 的第 3 方可执行less
工具(因为它不会启用管道等)(当然有很多)。 我相信 PSCX 中有这样的东西,但是每当我尝试安装它时,我都会看到很多冲突,而且我不确定使用-AllowClobber
以防它破坏其他东西。 也许在那一点上,如果那里有一个less
的东西,有没有人能够分离出该功能并独立于 PSCX 使用?
Get-Help Get-ChildItem -Full | less
Get-Help Get-ChildItem -Full | less
在类 Unix 平台上工作得很好,使用给定平台的less
实用程序(通常为/usr/bin/less
) - 不需要额外的工作。
我不是在追求 3rd 方可执行的
less
工具(因为它不会启用管道等)
任何从stdin (标准输入)读取并输出到stdout (标准输出)的外部程序(实用程序)根据定义是启用管道的,尽管总是仅针对文本:发送到此类实用程序的数据被转换为文本,并返回数据从这些实用程序被解释为文本。
在Windows 上,默认情况下只有 - 功能受限 - more.com
寻呼机可用- 见下文。
但是,可以在 Windows 上安装less
:
如果您安装了WSL的 Linux 发行版,您可以简单地通过管道传输到wsl less
; 例如:
Get-Help Get-ChildItem | wsl less
否则,考虑安装less.exe
Windows控制台应用程序(挑最近的文件夹中的版本),这是一部分GnuWin项目(安装程序需要管理员权限)。
注意:Windows 还有一个less
端口,它与其他实用程序捆绑在一起; 还没有亲自尝试过: UnxUtils 。
注意事项:
less
明显地期望 UTF-8 input ,而不管活动的 OEM 代码页如何,另外,如果[console]::OutputEncoding]
设置为 UTF-8,则仅正确显示非 ASCII 字符。
因此,必须将$OutputEncoding
和[console]::OutputEncoding]
设置为 UTF-8 ( [Text.Utf8Encoding]::new()
) 才能正常显示非 ASCII 字符。 (在 PowerShell [Core] v6+ 中, $OutputEncoding
默认为 UTF-8,但[console]::OutputEncoding]
仍反映系统的 OEM 代码页。)
有关如何使命令more
/PowerShell 中的help
功能使用less
而不是more.com
,请参阅底部部分,通过自定义的more
函数也确保使用 UTF-8 编码。
GnuWin less.exe
版本394
(在撰写本文时为less.exe
版本,但于 2006-01-03 发布)有时会运行不稳定less.exe
显示任何内容; 开始一个新的会话会使问题消失。
- 不那么强大(没有双关语) - Windows 对应的less
是more
( more.com
) ,它通过 stdin / 管道或通过文件名参数接受文本。
值得注意的是, more.com
似乎只支持向下翻页,有空格,不支持备份; 也就是说,您无法向后滚动 - 请参阅此处。
PowerShell 自己的Out-Host -Paging
也有同样的限制。
Windows PowerShell提供了一个围绕more.com
的内置包装函数,也命名为more
(这意味着执行more
执行该函数),它确保指定文件的内容以活动 OEM 代码页的编码输出,即more.com
期待什么。
PowerShell [Core] 6+ 不再提供此包装器。
在这两个版本中,内置的help
函数本身封装了Get-Help
,隐式地将后者的输出传递到more
- 在 Windows PowerShell 中,默认情况下在 Windows 上的 PowerShell 6+ 中(在 Unix 上,它默认为less
。
在 PowerShell 6+ 中,您还可以通过将$env:PAGER
变量设置为要调用以用于分页help
输出的命令行来定义自定义分页器。
在 Windows PowerShell 中,您唯一的选择是替换/定义自定义的more
函数(这也适用于 PowerShell 6+)。
换句话说:默认情况下,类似以下内容为您提供交互式分页输出:
help Get-ChildItem # Effectively the same as: Get-Help Get-ChildItem | more
less
并且想要使用它而不是more
: 覆盖内置的 / 定义一个more
函数如下(在你的$PROFILE
文件中):
less
:# Via WSL
function more {
$prevOe, $prevCoe = $OutputEncoding, [console]::OutputEncoding
try {
$OutputEncoding = [console]::OutputEncoding = [Text.Utf8Encoding]::new()
$Input | wsl less
}
finally {
$OutputEncoding, [console]::OutputEncoding = $prevOe, $prevCoe
}
}
# If running PowerShell Core (v6+):
# Force the `help` function to use the custom function.
if ($IsCoreClr) { $env:PAGER = 'more' }
less.exe
使用:# Via GnuWin (assuming the default installation location)
function more {
$prevOe, $prevCoe = $OutputEncoding, [console]::OutputEncoding
try {
$OutputEncoding = [console]::OutputEncoding = [Text.Utf8Encoding]::new()
$Input | & 'C:\Program Files (x86)\GnuWin32\bin\less.exe'
}
finally {
$OutputEncoding, [console]::OutputEncoding = $prevOe, $prevCoe
}
}
# If running PowerShell Core (v6+):
# Force the `help` function to use the custom function.
if ($IsCoreClr) { $env:PAGER = 'more' }
注意:这使得more
只接受管道输入,但扩展函数以接受文件名参数也不难。
如果满足以下条件,则有一个更简单的解决方案,由David Hatch提出:
您已安装 GnuWin less.exe
。
您不需要支持非 ASCII 字符。
您这样做了,但是您的会话已经配置为将$OutputEncoding
和[console]::OutputEncoding
为 UTF-8。 ( $OutputEncoding
在 PowerShell [Core] v6+ 中默认为 UTF-8,但不是[console]::OutputEncoding]
)。
Windows PowerShell:
Set-Alias more 'C:\Program Files (x86)\GnuWin32\bin\less.exe'
PowerShell [核心] v6+:
$env:PAGER = 'C:\Program Files (x86)\GnuWin32\bin\less.exe'
我发现“少”和“多”可以正常工作。 经过查询,发现原因是安装了cygwin。
❯ Get-Command more
CommandType Name Version Source
----------- ---- ------- ------
Application more.exe
❯ Get-Command less CommandType Name Version Source
----------- ---- ------- ------
Application less.exe 0.0.0.0 C:\cygwin64\bin\less.exe
这部分是对“if_ok_button”的回复,但无法放入子评论中,但我使用以下(稍微复杂的)函数,如果我运行“def”或对象类型,该函数现在已成为我的工具包中的固定装置,就像一个变量,它会返回有关该事物的所有信息的摘要,而无需我找到正确的命令 - 我一直在构建它,现在它涵盖了很多(但如果有人有任何改进,我会感谢)。
例如 def dir、def more、def abc、def get-command、def gc、def
# Find definitions for any Cmdlet, Function, Alias, External Script, Application
function def {
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[ArgumentCompleter({ [Management.Automation.CompletionResult]::Command })]
[string]$cmd,
[switch]$Examples
)
function Write-Wrap {
[CmdletBinding()]Param( [parameter(Mandatory=1, ValueFromPipeline=1, ValueFromPipelineByPropertyName=1)] [Object[]]$chunk )
$Lines = @()
foreach ($line in $chunk) {
$str = ''; $counter = 0
$line -split '\s+' | % {
$counter += $_.Length + 1
if ($counter -gt $Host.UI.RawUI.BufferSize.Width) {
$Lines += ,$str.trim()
$str = ''
$counter = $_.Length + 1
}
$str = "$str$_ "
}
$Lines += ,$str.trim()
}
$Lines
}
$deferr = 0; $type = ""
try { $type = ((gcm $cmd -EA silent).CommandType); if ($null -eq $type) { $deferr = 1 } } catch { $deferr = 1 }
if ($deferr -eq 1) {
if ($cmd -eq $null) { Write-Host "Object is `$null" ; return }
Write-Host "`$object | Convert-Json:" -F Cyan
$cmd | ConvertTo-Json
""
Write-Host "(`$object).GetType()" -F Cyan -NoNewline ; Write-Host " :: [BaseType|Name|IsPublic|IsSerial|Module]"
($cmd).GetType() | % { "$($_.BaseType), $($_.Name), $($_.IsPublic), $($_.IsSerializable), $($_.Module)" }
""
Write-Host "`$object | Get-Member -Force" -F Cyan
$m = "" ; $cm = "" ; $sm = ""; $p = "" ; $ap = "" ; $cp = "" ; $np = "" ; $pp = "" ; $sp = "" ; $ms = ""
$msum = 0 ; $cmsum = 0 ; $smsum = 0 ; $psum = 0 ; $cpsum = 0 ; $apsum = 0 ; $spsum = 0 ; $ppsum = 0 ; $npsum = 0 ; $spsum = 0 ; $mssum = 0
$($cmd | Get-Member -Force) | % {
if ($_.MemberType -eq "Method") { if(!($m -like "*$($_.Name),*")) { $m += "$($_.Name), " ; $msum++ } }
if ($_.MemberType -eq "CodeMethod") { if(!($cm -like "*$($_.Name),*")) { $cm += "$($_.Name), " ; $cmsum++ } }
if ($_.MemberType -eq "ScriptMethod") { if(!($sm -like "*$($_.Name),*")) { $sm += "$($_.Name), " ; $smsum++ } }
if ($_.MemberType -eq "Property") { if(!($p -like "*$($_.Name),*")) { $p += "$($_.Name), " ; $psum++ } }
if ($_.MemberType -eq "AliasProperty") { if(!($ap -like "*$($_.Name),*")) { $ap += "$($_.Name), " ; $apsum++ } }
if ($_.MemberType -eq "CodeProperty") { if(!($cp -like "*$($_.Name),*")) { $cp += "$($_.Name), " ; $cpsum++ } }
if ($_.MemberType -eq "NoteProperty") { if(!($np -like "*$($_.Name),*")) { $np += "$($_.Name), " ; $npsum++ } }
if ($_.MemberType -eq "ParameterizedProperty") { if(!($pp -like "*$($_.Name),*")) { $pp += "$($_.Name), " ; $ppsum++} }
if ($_.MemberType -eq "ScriptProperty") { if(!($sp -like "*$($_.Name),*")) { $sp += "$($_.Name), " ; $npsum++ } }
if ($_.MemberType -eq "MemberSet") { if(!($ms -like "*$($_.Name),*")) { $ms += "$($_.Name), " ; $mssum++ } }
# AliasProperty, CodeMethod, CodeProperty, Method, NoteProperty, ParameterizedProperty, Property, ScriptMethod, ScriptProperty
# All, Methods, MemberSet, Properties, PropertySet
}
if($msum -ne 0) { Write-Wrap ":: Method [$msum] => $($m.TrimEnd(", "))" }
if($msum -ne 0) { Write-Wrap ":: CodeMethod [$cmsum] => $($cm.TrimEnd(", "))" }
if($msum -ne 0) { Write-Wrap ":: ScriptMethod [$smsum] => $($sm.TrimEnd(", "))" }
if($psum -ne 0) { Write-Wrap ":: Property [$psum] => $($p.TrimEnd(", "))" }
if($npsum -ne 0) { Write-Wrap ":: AliasProperty [$apsum] => $($ap.TrimEnd(", "))" }
if($npsum -ne 0) { Write-Wrap ":: CodeProperty [$cpsum] => $($cp.TrimEnd(", "))" }
if($npsum -ne 0) { Write-Wrap ":: NoteProperty [$npsum] => $($np.TrimEnd(", "))" }
if($ppsum -ne 0) { Write-Wrap ":: ParameterizedProperty [$ppsum] => $($pp.TrimEnd(", "))" }
if($spsum -ne 0) { Write-Wrap ":: ScriptProperty [$spsum] => $($sp.TrimEnd(", "))" }
if($mssum -ne 0) { Write-Wrap ":: ScriptProperty [$mssum] => $($ms.TrimEnd(", "))" }
""
Write-Host "`$object | Measure-Object" -F Cyan
$cmd | Measure-Object | % { "Count [$($_.Count)], Average [$($_.Average)], Sum [$($_.Sum)], Maximum [$($_.Maximum)], Minimum [$($_.Minimum)], Property [$($_.Property)]" }
}
if ($deferr -eq 0) {
if ($cmd -like '*`**') { Get-Command $cmd ; break } # If $cmd contains a *, then just check for commands, don't find definitions
if ($type -eq 'Cmdlet') {
Write-Host "`n'$cmd' is a Cmdlet:`n" -F Green
Write-Host "SYNOPSIS, DESCRIPTION, SYNTAX for '$cmd'. " -F Green
Write-Host "------------"
Write-Host ""
Write-Host "(Get-Help $cmd).Synopsis" -F Cyan
Write-Host "$((Get-Help $cmd).Synopsis)"
Write-Host ""
Write-Host "(Get-Help $cmd).Description.Text" -F Cyan
try {
$arrdescription = (Get-Help $cmd).Description.Text.split("`n")
foreach ($i in $arrdescription) { Write-Wrap $i }
} catch { "Could not resolve description for $cmd" }
Write-Host ""
Write-Host "(Get-Command $cmd -Syntax)" -F Cyan
$arrsyntax = (Get-Command $cmd -syntax).TrimStart("").Split("`n") # Trim empty first line then split by line breaks
foreach ($i in $arrsyntax) { Write-Wrap $i } # Wrap lines properly to console width
Get-Alias -definition $cmd -EA silent # Show all defined aliases
Write-Host "`nThis Cmdlet is in the '$((Get-Command -type cmdlet $cmd).Source)' Module." -F Green
Write-Host ""
Write-Host ""
}
elseif ($type -eq 'Alias') {
Write-Host "`n'$cmd' is an Alias. " -F Green -NoNewLine ; Write-Host "This Alias is in the '$((get-command -type alias $cmd).ModuleName).' Module"
Write-Host ""
Write-Host "Get-Alias '$cmd' *or* cat alias:\$cmd" -F Cyan
cat alias:\$cmd # Write-Host "$(cat alias:\$cmd)" # "$((Get-Alias $cmd -EA silent).definition)"
if ($cmd -eq '?') { $cmd = '`?' } # To deal correctly with the wildcard '?'
"`n'$((Get-Alias $cmd).Name)' is an alias of '$((Get-Alias $cmd).ReferencedCommand)'"
$fulldef = (Get-Alias $cmd -EA silent).definition # Rerun def but using the full cmdlet or function name.
def $fulldef
if ($Examples -eq $true) { $null = Read-Host 'Press any key to view command examples' ; get-help $fulldef -examples }
}
elseif ($type -eq 'Function') {
Write-Host "`n'$cmd' is a Function. " -F Green -NoNewline
Write-Host "`ncat function:\$cmd (show contents of function)`n" -F Cyan ; cat function:\$cmd ; Write-Host ""
Write-Host "cat function:\$cmd`n" -F Cyan
Write-Host ""
Write-Host "SYNOPSIS, SYNTAX for '$cmd'. " -F Green
Write-Host "------------"
$arrsynopsis = ((Get-Help $cmd).Synopsis).TrimStart("").Split("`n") # Trim empty first line then split by line breaks
$arrsyntax = (Get-Command $cmd -syntax).TrimStart("").Split("`n") # Often synopsis=syntax for function so use Compare-Object
if ($null -eq $(Compare-Object $arrsynopsis $arrsyntax -SyncWindow 0)) {
Write-Host "'(Get-Help $cmd).Synopsis'" -F Cyan -N
Write-Host " and " -N
Write-Host "'Get-Command $cmd -Syntax'" -F Cyan -N
Write-Host " have the same output for this function:`n"
foreach ($i in $arrsynopsis) { Write-Wrap $i } # Wrap lines properly to console width
} else {
Write-Host "(Get-Help $cmd).Synopsis" -F Cyan
foreach ($i in $arrsynopsis) { Write-Wrap $i } # Wrap lines properly to console width
Write-Host ""
Write-Host "Get-Command $cmd -Syntax" -F Cyan
foreach ($i in $arrsyntax) { Write-Wrap $i } # Wrap lines properly to console width
}
Write-Host "The '$cmd' Function is in the '$((get-command -type function $cmd).Source)' Module." -F Green
Write-Host ""
if ($Examples -eq $true) { $null = Read-Host "Press any key to view command examples" ; get-help $cmd -examples }
Write-Host ""
}
elseif ($type -eq 'ExternalScript') { # For .ps1 scripts on path
$x = gcm $cmd
Write-Host "`n'$cmd' is an ExternalScript (i.e. a .ps1 file on the path)." -F Green
Write-Host "`n$($x.Path)`n" -F Green
Write-Host "`n$($x.ScriptContents)"
Write-Host ""
if ($Examples -eq $true) { $null = Read-Host "Press any key to view command examples" ; get-help $cmd -Examples }
elseif ($Synopsis -eq $true) { $null = Read-Host "Press any key to view command examples" ; (get-help $cmd).Synopsis }
elseif ($Syntax -eq $true) { $null = Read-Host "Press any key to view command examples" ; Get-Command $cmd -Syntax }
Write-Host ""
}
elseif ($type -eq 'Application') { # For .exe etc on path
Write-Host "`n'$cmd' was found. It is an Application (i.e. a .exe or similar located on the path)." -F Green
Write-Host "`n$(where.exe $cmd)" -F Green
Write-Host ""
Read-Host "Press any key to open cmd.exe and try '$cmd /?'" ; cmd.exe /c $cmd /? | more
Write-Host ""
}
} elseif ((get-module -ListAvailable -Name $cmd) -ne $null) {
# https://stackoverflow.com/questions/28740320/how-do-i-check-if-a-powershell-module-is-installed
""
(get-module $cmd).path
(get-module $cmd).ExportedFunctions
"ExportedCommands (also note: get-command -Module $cmd)"
(get-module custom-tools).ExportedCommands
""
echo "get-module $cmd | get-member # Just show the members"
echo "get-module $cmd | fl * # Show the contents of every member"
}
else {
if ($cmd.length -eq 0) { "`n'$cmd': No command definition found. The command may require to be surround by ' or `"`nif it contains special characters (such as 'def `"&`"').`n" }
else { "`nInput is not a command, so no command definition search.`n" }
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.