xlogI125’s blog

パソコン作業を効率化したい

PowerShell練習 フォルダのサイズを一覧で表示

メモ

  • 1つのフォルダのサイズを表示
    • Get-ChildItem -LiteralPath .\ -Force -Recurse | Where-Object {$_.psobject.properties.match('Length').Count -ne 0} | Measure-Object -Property Length -Sum

使い捨てスクリプト

Measure-Object -Property Length -Sum

  • フォルダは全てアクセスできる前提とします
# PowerShell 5.1, Windows 11

# ファイル名
#  "%USERPROFILE%\Desktop\FolderSizeMeasure.ps1"
# エンコード
#  UTF-8 (BOM付き)

# ショートカット(.lnk)
# リンク先(T):
#  PowerShell.exe -NoLogo -NoExit -ExecutionPolicy RemoteSigned -File "%USERPROFILE%\Desktop\FolderSizeMeasure.ps1"
# 作業フォルダー(S):
#  ""

# SendToフォルダ
#  %APPDATA%\Microsoft\Windows\SendTo

Set-StrictMode -Version Latest

Add-Type -Language CSharp -TypeDefinition @'
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.IO;

namespace MyNamespace {
  public class MyClass {
    [DllImport(
      "Shlwapi.dll", EntryPoint = "StrCmpLogicalW", CharSet = CharSet.Unicode
    )]
    public static extern int StrCmpLogicalW(
      [MarshalAs(UnmanagedType.LPWStr)] string psz1, 
      [MarshalAs(UnmanagedType.LPWStr)] string psz2
    );

    public static int SortStrCmpLW<T>(T obj1, T obj2) where T : FileSystemInfo {
      return StrCmpLogicalW(obj1.Name, obj2.Name);
    }

    public static T[] MySort<T>(T[] obj) where T : FileSystemInfo {
      List<T> tmp = new List<T>(obj);
      tmp.Sort(SortStrCmpLW<T>);
      return tmp.ToArray();
    }
  }
}
'@

# フォルダを取得
$gcis = [System.IO.FileSystemInfo[]]@(Get-ChildItem -Force -Directory)

# ソート
$gciSorts = [MyNamespace.MyClass]::MySort($gcis)

$pscObjs = [PSCustomObject[]]::new($gciSorts.Length)

for ($i = 0; $i -lt $pscObjs.Length; $i++) {
  $m = Get-ChildItem -LiteralPath $gciSorts[$i].FullName -Force -Recurse | 
        Where-Object {$_.psobject.properties.match('Length').Count -ne 0} | 
        Measure-Object -Property Length -Sum

  $pscObjs[$i] = [PSCustomObject]@{}

  $pscObjs[$i] | Add-Member -MemberType NoteProperty `
    -Name 'Name' -Value $($gciSorts[$i].Name)

  if ($m.psobject.properties.match('Sum').Count -ne 0) {
    $pscObjs[$i] | Add-Member -MemberType NoteProperty `
      -Name 'Length[MB]' -Value $([Math]::Round($m.Sum / 1024 / 1024, 3))
  } else {
    $pscObjs[$i] | Add-Member -MemberType NoteProperty `
      -Name 'Length[MB]' -Value $null
  }

}

if ($pscObjs.Length -gt 0) {
  $csv = $pscObjs | ConvertTo-Csv -NoTypeInformation
  $csv | Set-Clipboard
  ConvertFrom-Csv $csv
} else {
  $null | Set-Clipboard
}

FileSystemObject Folder.Size

  • エラー処理やCOMオブジェクトの解放を気にしてないので練習以外での実行は危険
# PowerShell 5.1, Windows 11

# ファイル名
#  "%USERPROFILE%\Desktop\FolderSizeFSO.ps1"
# エンコード
#  UTF-8 (BOM付き)

# ショートカット(.lnk)
# リンク先(T):
#  PowerShell.exe -NoLogo -NoExit -ExecutionPolicy RemoteSigned -File "%USERPROFILE%\Desktop\FolderSizeFSO.ps1"
# 作業フォルダー(S):
#  ""

# SendToフォルダ
#  %APPDATA%\Microsoft\Windows\SendTo

Set-StrictMode -Version Latest

Add-Type -Language CSharp -TypeDefinition @'
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.IO;

namespace MyNamespace {
  public class MyClass {
    [DllImport(
      "Shlwapi.dll", EntryPoint = "StrCmpLogicalW", CharSet = CharSet.Unicode
    )]
    public static extern int StrCmpLogicalW(
      [MarshalAs(UnmanagedType.LPWStr)] string psz1, 
      [MarshalAs(UnmanagedType.LPWStr)] string psz2
    );

    public static int SortStrCmpLW<T>(T obj1, T obj2) where T : FileSystemInfo {
      return StrCmpLogicalW(obj1.Name, obj2.Name);
    }

    public static T[] MySort<T>(T[] obj) where T : FileSystemInfo {
      List<T> tmp = new List<T>(obj);
      tmp.Sort(SortStrCmpLW<T>);
      return tmp.ToArray();
    }
  }
}
'@

# フォルダを取得
$gcis = [System.IO.FileSystemInfo[]]@(Get-ChildItem -Force -Directory)

# ソート
$gciSorts = [MyNamespace.MyClass]::MySort($gcis)

$pscObjs = [PSCustomObject[]]::new($gciSorts.Length)

$fso = [System.Activator]::CreateInstance(
  [System.Type]::GetTypeFromProgID("Scripting.FileSystemObject"))

for ($i = 0; $i -lt $pscObjs.Length; $i++) {
  $fld = $fso.GetFolder($gciSorts[$i].FullName)

  $pscObjs[$i] = [PSCustomObject]@{
    "Name" = $gciSorts[$i].Name
    "Length[MB]" = [Math]::Round($fld.Size / 1024 / 1024, 3)
  }

  $fld = $null
}

$fso = $null

if ($pscObjs.Length -gt 0) {
  $csv = $pscObjs | ConvertTo-Csv -NoTypeInformation
  $csv | Set-Clipboard
  ConvertFrom-Csv $csv
} else {
  $null | Set-Clipboard
}