Last active
December 23, 2024 23:23
-
-
Save sba923/d0d5ad16f2b12d7785adf830b0395dc2 to your computer and use it in GitHub Desktop.
*nix work-alike's for PowerShell: df, dirname, whatis, whence
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# this is one of Stéphane BARIZIEN's public domain scripts | |
# the most recent version can be found at: | |
# https://gist.github.com/sba923/d0d5ad16f2b12d7785adf830b0395dc2#file-df-ps1 | |
function Format-AsKMG | |
{ | |
param ($bytes,$precision='0') | |
foreach ($i in ("","KB","MB","GB","TB")) | |
{ | |
if (($bytes -lt 1000) -or ($i -eq "TB")) | |
{ | |
$bytes = ($bytes).tostring("F0" + "$precision") | |
if ($i -eq '') | |
{ | |
return $bytes | |
} | |
else | |
{ | |
return $bytes + " $i" | |
} | |
} | |
else | |
{ | |
$bytes /= 1KB | |
} | |
} | |
} | |
Get-CimInstance -ClassName win32_logicaldisk | ` | |
Select-Object DeviceID, VolumeName, Size, Freespace | ` | |
ForEach-Object { | |
$psdrive = Get-PSDrive -name $_.DeviceID.Substring(0,1) -ErrorAction SilentlyContinue | Where-Object { $_.Name -ceq $_.Name.ToUpper() } | |
try | |
{ | |
# work around issue in PowerShell 7.4 where the mount point is not returned correctly for network-mounted drive letters | |
# see https://github.com/PowerShell/PowerShell/issues/19903 | |
if ($psdrive.DisplayRoot -match 'System\.Span') | |
{ | |
$uncpath = @((net use) -match ('\s+' + $psdrive.Name + ':\s+.*Microsoft Windows Network'))[0] -replace ('.*' + $psdrive.Name + ':\s+(\\\\.*\S)\s+Microsoft Windows Network'), '$1' | |
Add-Member -InputObject $_ -MemberType NoteProperty -Name MountedOn -Value $uncpath | |
} | |
elseif ($psdrive.DisplayRoot -ne ($psdrive.Name + ':\')) | |
{ | |
# work around issue in PowerShell 7.4.1 where the DisplayRoot property is "padded with NULs" | |
# see https://github.com/PowerShell/PowerShell/issues/21064 | |
$displayroot = $psdrive.DisplayRoot | |
if ($displayroot.Contains([char]0)) | |
{ | |
$displayroot = $displayroot.Substring(0,$displayroot.IndexOf([char]0)) | |
} | |
Add-Member -InputObject $_ -MemberType NoteProperty -Name MountedOn -Value $displayroot | |
} | |
else | |
{ | |
Add-Member -InputObject $_ -MemberType NoteProperty -Name MountedOn -Value $null | |
} | |
} | |
catch | |
{ | |
Add-Member -InputObject $_ -MemberType NoteProperty -Name MountedOn -Value $null | |
} | |
$_ | |
} | ` | |
Format-Table -AutoSize ` | |
DeviceID, ` | |
VolumeName, ` | |
MountedOn, ` | |
@{Name='Size'; Expression={Format-AsKMG -bytes $_.size -precision 1}; Align='right'}, ` | |
@{Name='Freespace'; Expression={Format-AsKMG -bytes $_.Freespace -precision 1}; Align='right'}, ` | |
@{Name='PercentFree'; Expression={"{0:n2}" -f ($_.freespace / $_.size * 100)}; Align='right'}, ` | |
@{Name='PercentUsed'; Expression={"{0:n2}" -f ((1-($_.freespace / $_.size)) * 100)}; Align='right'} | |
$null = $true | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# this is one of Stéphane BARIZIEN's public domain scripts | |
# the most recent version can be found at: | |
# https://gist.github.com/sba923/d0d5ad16f2b12d7785adf830b0395dc2#file-dirname-ps1 | |
param([string] $literalpath) | |
try | |
{ | |
$item = Get-Item -LiteralPath $literalpath -ErrorAction SilentlyContinue | |
$parent = Split-Path -Path $item.FullName -Parent | |
$parent | |
} | |
catch | |
{ | |
$null | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# this is one of Stéphane BARIZIEN's public domain scripts | |
# the most recent version can be found at: | |
# https://gist.github.com/sba923/d0d5ad16f2b12d7785adf830b0395dc2#file-whatis-ps1 | |
param([string] $Name, [switch] $ReturnPath, [switch] $Quiet) | |
Set-StrictMode -Version Latest | |
#region Get-ExecutableType | |
# derived from https://gallery.technet.microsoft.com/scriptcenter/Identify-16-bit-32-bit-and-522eae75 | |
function Get-ExecutableType | |
{ | |
<# | |
.Synopsis | |
Determines whether an executable file is 16-bit, 32-bit or 64-bit. | |
.DESCRIPTION | |
Attempts to read the MS-DOS and PE headers from an executable file to determine its type. | |
The command returns one of four strings (assuming no errors are encountered while reading the | |
file): | |
"Unknown", "16-bit", "x86", "x64", "ARM64", "ARM", "IA64" or if another PE machine field value, 0xNNNN | |
.PARAMETER Path | |
Path to the file which is to be checked. | |
.EXAMPLE | |
Get-ExecutableType -Path C:\Windows\System32\more.com | |
.INPUTS | |
None. This command does not accept pipeline input. | |
.OUTPUTS | |
String | |
.LINK | |
http://msdn.microsoft.com/en-us/magazine/cc301805.aspx | |
#> | |
[CmdletBinding()] | |
param ( | |
[Parameter(Mandatory = $true)] | |
[ValidateScript( { Test-Path -LiteralPath $_ -PathType Leaf })] | |
[string] | |
$Path | |
) | |
try | |
{ | |
try | |
{ | |
$stream = New-Object System.IO.FileStream( | |
$PSCmdlet.GetUnresolvedProviderPathFromPSPath($Path), | |
[System.IO.FileMode]::Open, | |
[System.IO.FileAccess]::Read, | |
[System.IO.FileShare]::Read | |
) | |
} | |
catch | |
{ | |
throw "Error opening file $Path for Read: $($_.Exception.Message)" | |
} | |
$exeType = 'Unknown' | |
if ([System.IO.Path]::GetExtension($Path) -eq '.COM') | |
{ | |
# 16-bit .COM files may not have an MS-DOS header. We'll assume that any .COM file with no header | |
# is a 16-bit executable, even though it may technically be a non-executable file that has been | |
# given a .COM extension for some reason. | |
$exeType = '16-bit' | |
} | |
$bytes = New-Object byte[](4) | |
if ($stream.Length -ge 64 -and | |
$stream.Read($bytes, 0, 2) -eq 2 -and | |
$bytes[0] -eq 0x4D -and $bytes[1] -eq 0x5A) | |
{ | |
$exeType = '16-bit' | |
if ($stream.Seek(0x3C, [System.IO.SeekOrigin]::Begin) -eq 0x3C -and | |
$stream.Read($bytes, 0, 4) -eq 4) | |
{ | |
if (-not [System.BitConverter]::IsLittleEndian) { [Array]::Reverse($bytes, 0, 4) } | |
$peHeaderOffset = [System.BitConverter]::ToUInt32($bytes, 0) | |
if ($stream.Length -ge $peHeaderOffset + 6 -and | |
$stream.Seek($peHeaderOffset, [System.IO.SeekOrigin]::Begin) -eq $peHeaderOffset -and | |
$stream.Read($bytes, 0, 4) -eq 4 -and | |
$bytes[0] -eq 0x50 -and $bytes[1] -eq 0x45 -and $bytes[2] -eq 0 -and $bytes[3] -eq 0) | |
{ | |
$exeType = 'Unknown' | |
if ($stream.Read($bytes, 0, 2) -eq 2) | |
{ | |
if (-not [System.BitConverter]::IsLittleEndian) { [Array]::Reverse($bytes, 0, 2) } | |
$machineType = [System.BitConverter]::ToUInt16($bytes, 0) | |
switch ($machineType) # see https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#machine-types | |
{ | |
0x014C { $exeType = 'x86' } | |
0x0200 { $exeType = 'IA64' } | |
0x8664 { $exeType = 'x64' } | |
0xAA64 { $exeType = 'ARM64' } | |
0x01C4 { $exeType = 'ARM' } | |
default { $exeType = ('0x{0:X4}' -f $machineType) } | |
} | |
} | |
} | |
} | |
} | |
return $exeType | |
} | |
catch | |
{ | |
throw | |
} | |
finally | |
{ | |
if ($null -ne $stream) { $stream.Dispose() } | |
} | |
} | |
#endregion | |
$gcm = $null | |
try | |
{ | |
$gcm = @(Get-Command -Name $Name -ErrorAction SilentlyContinue -All) | |
} | |
catch | |
{ | |
$gcm = $null | |
} | |
if ($null -eq $gcm -or $gcm.Count -eq 0) | |
{ | |
if (!$Quiet) | |
{ | |
Write-Host("'{0}' is not a known command" -f $Name) | |
} | |
else | |
{ | |
$null | |
} | |
Exit(1) | |
} | |
if ($gcm.Count -gt 1) | |
{ | |
Write-Host("WARNING: there is more than one resolution for '{0}', using the default one as reported by Get-Command" -f $Name) | |
$gcm = Get-Command -Name $Name -ErrorAction SilentlyContinue | |
} | |
else | |
{ | |
$gcm = $gcm[0] | |
} | |
$cmdtype = $gcm.CommandType | |
if (($cmdtype -eq 'Application') -and ($gcm.Path -match '\.cmd$')) | |
{ | |
$cmdtype = 'CMD script' | |
} | |
$cmdtype_s = $cmdtype.ToString().ToLower() | |
if ($cmdtype_s[0] -in @('a', 'e', 'i', 'o', 'u')) | |
{ | |
$article = 'an' | |
} | |
else | |
{ | |
$article = 'a' | |
} | |
if ($cmdtype -eq 'CMD script') | |
{ | |
$cmdtype_s = $cmdtype | |
} | |
if (!$ReturnPath) | |
{ | |
Write-Host("'{0}' is {1} {2}" -f $Name, $article, $cmdtype_s) | |
} | |
switch ($cmdtype) | |
{ | |
'Application' | |
{ | |
if (!$ReturnPath) | |
{ | |
$itempath = $gcm.Path | |
$item = Get-Item -LiteralPath $itempath | |
if ($item.Length -ne 0) | |
{ | |
Write-Host("Executable path is '{0}'" -f $gcm.Path) | |
Write-Host("Description: '{0}'" -f $item.VersionInfo.FileDescription) | |
Write-Host("Product version: '{0}'" -f $item.VersionInfo.ProductVersion) | |
Write-Host("Executable type: {0}" -f (Get-ExecutableType -Path $itempath)) | |
} | |
else | |
{ | |
if ($item.Attributes -band [System.IO.FileAttributes]::ReparsePoint) | |
{ | |
if ($null -ne $item.Target) | |
{ | |
$target = Get-Item -LiteralPath $item.Target -ErrorAction SilentlyContinue | |
if ($null -ne $target) | |
{ | |
if ($item.Target.GetType().Name -match '\[\]') # weirdly, this is an array | |
{ | |
if ($item.Target.Count -eq 1) | |
{ | |
$targetpath = $item.Target[0] | |
} | |
else | |
{ | |
throw ("Cannot determine target path for {0}: Target property is an array with more than one element" -f $item.FullName) | |
} | |
} | |
else | |
{ | |
$targetpath = $item.Target | |
} | |
Write-Host("Executable path is '{0}'" -f $targetpath) | |
Write-Host("Description: '{0}'" -f $target.VersionInfo.FileDescription) | |
Write-Host("Product version: '{0}'" -f $target.VersionInfo.ProductVersion) | |
Write-Host("Executable type: {0}" -f (Get-ExecutableType -Path $targetpath)) | |
} | |
else | |
{ | |
Write-Error ("Cannot access reparse point target '{0}'" -f $item.Target) | |
} | |
} | |
else | |
{ | |
Write-Error ("Cannot determine target for AppX reparse point '{0}'" -f $item.FullName) | |
} | |
} | |
else | |
{ | |
Write-Host -ForegroundColor Magenta ("'{0}' is a 0-byte file!!!???" -f $gcm.Path) | |
} | |
} | |
} | |
else | |
{ | |
$itempath = $gcm.Path | |
$item = Get-Item -LiteralPath $itempath | |
if ($item.Length -ne 0) | |
{ | |
$gcm.Path | |
} | |
else | |
{ | |
if ($item.Attributes -band [System.IO.FileAttributes]::ReparsePoint) | |
{ | |
if ($null -ne $item.Target) | |
{ | |
$target = Get-Item -LiteralPath $item.Target -ErrorAction SilentlyContinue | |
if ($null -ne $target) | |
{ | |
$item.Target | |
} | |
else | |
{ | |
Write-Error ("Cannot access reparse point target '{0}'" -f $item.Target) | |
$null | |
} | |
} | |
else | |
{ | |
Write-Error ("Cannot determine target for AppX reparse point '{0}'" -f $item.FullName) | |
$null | |
} | |
} | |
else | |
{ | |
Write-Host -ForegroundColor Magenta ("'{0}' is a 0-byte file!!!???" -f $gcm.Path) | |
$null | |
} | |
} | |
} | |
} | |
'Alias' | |
{ | |
if (!$ReturnPath) | |
{ | |
Write-Host("Resolves to: '{0}'" -f $gcm.Definition) | |
} | |
} | |
'Cmdlet' | |
{ | |
if (($gcm.Module -ne '') -and ($gcm.Module -notmatch '^Microsoft\.PowerShell')) | |
{ | |
if (!$ReturnPath) | |
{ | |
Write-Host("Implemented in module '{0}'" -f $gcm.Module) | |
} | |
} | |
} | |
'ExternalScript' | |
{ | |
if (!$ReturnPath) | |
{ | |
Write-Host("Path is '{0}'" -f $gcm.Path) | |
} | |
else | |
{ | |
$gcm.Path | |
} | |
} | |
'Function' | |
{ | |
if ($ReturnPath) | |
{ | |
"function:{0}" -f $Name | |
} | |
} | |
'CMD script' | |
{ | |
if (!$Name) | |
{ | |
Write-Host("Script path is '{0}'" -f $gcm.Path) | |
} | |
else | |
{ | |
$gcm.Path | |
} | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# this is one of Stéphane BARIZIEN's public domain scripts | |
# the most recent version can be found at: | |
# https://gist.github.com/sba923/d0d5ad16f2b12d7785adf830b0395dc2#file-whence-ps1 | |
param([string] $Name, [switch] $quiet) | |
. whatis.ps1 -Name $Name -ReturnPath -Quiet:$quiet | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
FWIW: The discussion at PowerShell/PowerShell#15079 didn't end up anywhere 😢