Reputation: 4080
When I run the following Get-Command Get-ChildItem -Syntax
I get:
<... empty line here ...>
Get-ChildItem [[-Path] <string[]>] [[-Filter] <string>] [-Include <string[]>] [-Exclude <string[]>] [-Recurse] [-Depth <uint32>] [-Force] [-Name] [-UseTransaction] [-Attributes <FlagsExpression[FileAttributes]>] [-Directory] [-File] [-Hidden] [-ReadOnly] [-System] [<CommonParameters>]
<... empty line here ...>
Get-ChildItem [[-Filter] <string>] -LiteralPath <string[]> [-Include <string[]>] [-Exclude <string[]>] [-Recurse] [-Depth <uint32>] [-Force] [-Name] [-UseTransaction] [-Attributes <FlagsExpression[FileAttributes]>] [-Directory] [-File] [-Hidden] [-ReadOnly] [-System] [<CommonParameters>]
<... empty line here ...>
However, this is not how I would like things to format and would prefer to strip the empty lines, and to prefix each syntax line with a #
(so that when the lines wrap, it's clear where each syntax definition starts). This is just an example, want to do similar with many Cmdlet outputs etc, to be able to manipulate the output as text with no empty lines above, below or in between, just the text, formatted and compact, so would really appreciate in general how to format in this way. i.e.
# Get-ChildItem [[-Path] <string[]>] [[-Filter] <string>] [-Include <string[]>] [-Exclude <string[]>] [-Recurse] [-Depth <uint32>] [-Force] [-Name] [-UseTransaction] [-Attributes <FlagsExpression[FileAttributes]>] [-Directory] [-File] [-Hidden] [-ReadOnly] [-System] [<CommonParameters>]
# Get-ChildItem [[-Filter] <string>] -LiteralPath <string[]> [-Include <string[]>] [-Exclude <string[]>] [-Recurse] [-Depth <uint32>] [-Force] [-Name] [-UseTransaction] [-Attributes <FlagsExpression[FileAttributes]>] [-Directory] [-File] [-Hidden] [-ReadOnly] [-System] [<CommonParameters>]
Can anyone advise on an easy way to achieve formatting output like that please?
Upvotes: 1
Views: 218
Reputation: 4080
Here was my current use for this. I find navigating Modules to be awkward and wanted a better/faster way to get a compact overview. I keep these in my personal Custom-Tools.psm1
Module and it helps me to very quickly see what's on a system.
Type mods
to see all installed Modules and where they are located.
Type mods <partial_name>
to see all matches. e.g. mods mic
or mods soft
Type mod <module-name>
to see quick details on the contents of a given Module.
Type mod <module-name> -i | more
to get all syntax details on the contents of that Module.
I find this to be a very quick and convenient way to interrogate Modules. Hopefully of use to some folks.
mods
function mods ($search) {
""
":: Complete `$env:PSModulePath string:`n"
$env:PSModulePath
$env:PSModulePath -Split ";" -replace "\\+$", "" | sort
""
""
$PathArray = $env:PSModulePath -Split ";" -replace "\\+$", "" | sort
""
foreach ($Path in $PathArray) {
if ($Path -ne '') {
$Path = $Path.TrimEnd('\')
echo ":: Modules under '$Path':`n"
# if (Test-Path $Path) {
$temp = (dir "$Path\*$search*" -Directory -EA Silent | Select -ExpandProperty Name) -join ", " # mods w* => mods w** which resolves fine
if ($temp -eq "") { "No matches for '$search' exist in this path" }
# } else { "This path is in `$env:PSModulePath but the folder does not exist"}
Write-Wrap $temp
""
}
}
""
}
mod
function mod ($Module, $def, [switch]$ShowModulesHere, [switch]$Info) {
if ($null -eq $Module) { "You must specify a Module to examine. Run 'mods' to see available Modules." ; break }
""
if ([bool](Get-Module $Module -ListAvailable) -eq $true) {
if ([bool](Get-Module $Module) -eq $true) { ":: Module '$Module' is already imported, so all functions are available`n" }
else { ":: Module '$Module' was not imported, running import now ..." ; Import-Module $Module }
}
else { "Could not find Module in available Module folders`n" ; break }
$ModulePath = ((Get-Module $Module | select Path).Path).TrimEnd('\')
$ModuleVer = (Get-Module $Module -ListAvailable | select Version).Version | sls "\d"
":: '$Module' is version $($ModuleVer)`n`n$ModulePath"
$ModuleRoot = Split-Path ((Get-Module $Module | select Path).Path).TrimEnd("\")
$ModulesHere = (dir $Path -Directory | Select -ExpandProperty Name) -join ", "
if ($Info) {
""
foreach ($i in (Get-Command -Module $Module).Name) {
$out = $i # Parse the info string from after the "{"
$type = "" ; try { $type = ((gcm $i -EA silent).CommandType); } catch { $deferr = 1 }
$out += " # $type"
$syntax = Get-Command $i -Syntax
$definition = "" ; if ($type -eq "Alias") { $definition = (get-alias $i).Definition }
$syntax = $syntax -replace $definition, ""
if ($type -eq "Alias") { $out += " for '$definition'" }
$out
if ($type -eq "Function") { $syntax = $syntax -replace $i, "" }
if ($type -eq "Cmdlet") { $syntax = $syntax -replace $i, "" }
if (!([string]::IsNullOrWhiteSpace($syntax))) {
$syntax -split '\r\n' | where {$_} | foreach { "Syntax => $_" | Write-Wrap }
}
""
}
""
}
else {
""
":: Module functions:"
$out = ""; foreach ($i in (Get-Command -Module $Module).Name) { $out += " $i," } ; "" ; Write-Wrap $out.TrimEnd(", ")
""
}
$ModPaths = $env:PSModulePath -Split ";" -replace "\\+$", "" | sort
":: Module Paths (`$env:PSModulePath):"
foreach ($i in $ModPaths) { " $i"}
""
":: '$Module' Path:`n`n $ModulePath"
""
foreach ($i in $ModPaths) {
if (!([string]::IsNullOrWhiteSpace($i))) {
if ($ModulePath | sls $i -SimpleMatch) { $ModRoot = $i ; ":: `$env:PSModulePath parent location is:`n`n $i" }
}
}
""
if ($def -ne $null) {
":: Press any key to open '$def' definition:"
pause
""
def $def
""
}
if ($ShowModulesHere -eq $true) {
":: This `$env:PSModulePath root also contains the following Modules:"
""
(dir $ModRoot -Directory | Select -ExpandProperty Name) -join ", "
""
}
}
Upvotes: 0
Reputation: 4080
That's fantastic, thanks Doug, really useful. I also use a small function that assists me in nicely formatting line-wraps, so I can then use your code to get around the max width:
(Get-Command Get-ChildItem -Syntax) -split '\r\n' | where {$_} | foreach {"# $_"} | Write-Wrap
Where the Write-Wrap
function always formats cleanly to the width of the console (edited with mklment0's points below, and with the essential PROCESS block that he pointed out):
function Write-Wrap {
[CmdletBinding()]Param( [parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] [Object[]]$chunk )
PROCESS {
$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
}
}
Upvotes: 0
Reputation: 8868
Here you go!
(Get-Command Get-ChildItem -Syntax) -split '\r\n' |
where {$_} | foreach {"# $_"}
# Get-ChildItem [[-Path] <string[]>] [[-Filter] <string>] [-Include <string[]>] [-Exclude <string[]>] [-Recurse] [-Depth <uint32>] [-Force] [-Name] [-UseTransaction] [-Attributes <FlagsExpression[FileAttributes]>] [-Directory] [-File] [-Hidden] [-ReadOnly] [-System] [<CommonParameters>]
# Get-ChildItem [[-Filter] <string>] -LiteralPath <string[]> [-Include <string[]>] [-Exclude <string[]>] [-Recurse] [-Depth <uint32>] [-Force] [-Name] [-UseTransaction] [-Attributes <FlagsExpression[FileAttributes]>] [-Directory] [-File] [-Hidden] [-ReadOnly] [-System] [<CommonParameters>]
You will be bound by the max width of the console so even if they are one line it will wrap. You could pipe into clip
if you want to paste it into something else.
(Get-Command Get-ChildItem -Syntax) -split '\r\n' |
where {$_} | foreach {"# $_"} | clip
Upvotes: 2