Last active
May 19, 2017 21:16
-
-
Save sean-m/a7c8dcf3e98bdd287c7f76c77de03518 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
function Get-FileSize { | |
<# | |
.Synopsis | |
Gets file info, recursively if desired. | |
.DESCRIPTION | |
Enumerates files in a directory getting both the regular | |
and compressed size. The enumeration happens in a pipeline | |
function so it's memory efficient. The input parameter $Path | |
is checked for type so if you pipe the output of Get-ChildItem | |
into the function it will use the FullName parameter as the path. | |
Sean McArdle, Nov 2017 | |
.EXAMPLE | |
Get-FileSize $env:temp | select FullName, Length, SizeOnDisk | FT -AutoSize | |
#> | |
[CmdletBinding()] | |
[OutputType([PSObject])] | |
param ( | |
[Parameter(Mandatory=$true, | |
ValueFromPipeline=$true, | |
ValueFromPipelineByPropertyName=$true, | |
Position=0)] | |
$Path, | |
[Parameter(Mandatory=$false, | |
ValueFromPipeline=$true, | |
ValueFromPipelineByPropertyName=$true, | |
Position=1)] | |
[switch]$Recurse, | |
[switch]$NoCompressCheck | |
) | |
begin { | |
$ntype =@" | |
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Runtime.InteropServices; | |
using System.Text; | |
public class NativeHelper_File { | |
[DllImport("kernel32.dll", SetLastError = true)] | |
private static extern uint GetCompressedFileSizeW([In, MarshalAs(UnmanagedType.LPWStr)] string lpFileName, [Out, MarshalAs(UnmanagedType.U4)] out uint lpFileSizeHigh); | |
public static UInt64 GetCompressedFileSize(string FilePath, bool ErrAsZero=false) { | |
uint highSize; | |
uint lowSize = GetCompressedFileSizeW(FilePath, out highSize); | |
int err = Marshal.GetLastWin32Error(); | |
if (highSize == 0 && lowSize == 0xFFFFFFFF && err != 0) { | |
if (ErrAsZero) return 0; | |
throw new System.ComponentModel.Win32Exception(err); | |
} | |
return ((ulong)highSize << 32 | lowSize); | |
} | |
[DllImport("shlwapi.dll", CharSet = CharSet.Auto)] | |
private static extern bool PathCompactPathEx([Out] StringBuilder pszOut, string szPath, int cchMax, int dwFlags); | |
public static string PathCompactPath(string Path) { | |
StringBuilder sb = new StringBuilder(247); | |
PathCompactPathEx(sb, Path, 246, 0); | |
return sb.ToString(); | |
} | |
public static IEnumerable<string> GetFiles(string root, string searchPattern, bool Recurse = false) { | |
var pending = new Stack<string>(); | |
pending.Push(root); | |
while (pending.Count != 0) { | |
var path = pending.Pop(); | |
string[] next = null; | |
try { | |
next = Directory.GetFiles(path, searchPattern); | |
} | |
catch { } | |
if (next != null && next.Length != 0) | |
foreach (var file in next) yield return file; | |
try { | |
if (Recurse) { | |
next = Directory.GetDirectories(path); | |
foreach (var subdir in next) pending.Push(subdir); | |
} | |
} | |
catch { } | |
} | |
} | |
} | |
"@ | |
if(-not ([System.Management.Automation.PSTypeName]'NativeHelper_File').Type) { | |
Add-Type -TypeDefinition $ntype -Language CSharp -IgnoreWarnings | |
} | |
} | |
process { | |
## Check if taking in FileInfo objects, | |
$unwrap = $false | |
$unwrap = [bool]($Path.GetType() -like [System.IO.DirectoryInfo]) | |
$filter = "*.*" | |
$p = [String]::Empty | |
if ($unwrap) { | |
$p = $Path.FullName | |
} | |
else { | |
$p = $Path | |
} | |
foreach ($fname in [NativeHelper_File]::GetFiles($p, $filter, $Recurse)) { | |
[UInt64]$size = 0 | |
[UInt64]$csize = 0 | |
## Handle long path name | |
if ($fname.Length -gt 247) { | |
$fname = [NativeHelper_File]::PathCompactPath($fname) | |
} | |
## Get FileInfo | |
$f = New-Object System.IO.FileInfo $fname | |
## File size on disk | |
if ((-not $NoCompressCheck) -and ` | |
($f.Attributes.HasFlag([System.IO.FileAttributes]::Compressed))) { | |
$csize = $csize + [NativeHelper_File]::GetCompressedFileSize($fname, $true) | |
} | |
else { | |
$csize = $f.Length | |
} | |
$f | Add-Member -MemberType NoteProperty -Name SizeOnDisk -Value $csize -Passthru | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment