使用powershell在磁盘上查找目录空间

时间:2014-12-15 02:52:53

标签: powershell directory get-childitem diskusage

我想知道我的不同子目录的大小,所以我在SO和其他地方跟踪了Getting Directory sizes powershellDisplay directory structure in powershell以及其他一些的指示。这些功能运行良好,除了我想知道一些部分同步的文件夹占用磁盘的空间(例如,我在Skydrive中有一个文件夹,只有一些子文件夹在线可用)。当我调用任一函数时,它们会报告文件夹的大小,就像它在磁盘中一样,而不是实际的磁盘使用情况。如果我右键单击该文件夹并检查其属性,我可以清楚地看到sizesize in disk之间存在差异。

我尝试使用Sort-Object -Property SizeSort-Object -Property Length切换到任一函数(主要基于Get-ChildItem函数),但它们都返回大小而不是磁盘大小。

我想有一个简单的开关,只考虑实际的磁盘使用量,而不是总大小,但我完全失去了如何实现它。任何线索都非常感谢!

谢谢,

2 个答案:

答案 0 :(得分:2)

磁盘大小是文件在驱动器上占用的实际大小,具体取决于群集大小(或分配单元),大多数时间是4KB,但不是所有时间。这取决于文件格式及其格式。

只要文件没有被压缩,就可以找出需要多少块的簇才能适合每个文件。请记住,如果文件小于群集大小,它将占用一个分配单元。

如果文件已压缩,则信息不易获取,需要通过API检索。

以下代码分为3个主要部分:

  1. 它定义了一个用于访问kernel.dll中的函数GetCompressedFileSizeAPI的Type。此函数将检索文件磁盘上的压缩大小。
  2. 它使用WMI来确定给定$path
  3. 的群集大小
  4. 它计算文件夹和子文件夹$path中文件的大小,具体取决于文件是否已压缩。
  5. 请注意,对Get-ChildItem的调用使用-force开关来确保我们也检索隐藏文件和系统文件。

    我不确定此代码是否适用于Skydrive,因此您可能需要更改WMI部分。

    $path = '.\'
    
    Add-Type -TypeDefinition @" 
    using System;
    using System.Runtime.InteropServices;
    using System.ComponentModel;
    
    public class FileInfo 
    { 
        [DllImport("kernel32.dll", SetLastError=true, EntryPoint="GetCompressedFileSize")]
        static extern uint GetCompressedFileSizeAPI(string lpFileName, out uint lpFileSizeHigh);
    
        public static ulong GetCompressedFileSize(string strFileName)
        {
            uint intHigh;
            uint intLow;
            intLow = GetCompressedFileSizeAPI(strFileName, out intHigh);
            int intError = Marshal.GetLastWin32Error();
            if (intHigh == 0 && intLow == 0xFFFFFFFF && intError != 0)
                throw new Win32Exception(intError);
            else
                return ((ulong)intHigh << 32) + intLow;
        }
    } 
    "@
    
    
    $files = Get-ChildItem $path -Recurse -force | where {$_.PSIsContainer -eq $false}
    
    $drive = [string]$files[0].PSdrive+':'
    $wql = "SELECT Blocksize FROM Win32_Volume where DriveLetter='$drive'"
    $driveinfo = Get-WmiObject -Query $wql -ComputerName '.' 
    
    $sizeondisk = ($files | %{      
        if ($_.Attributes -like "*compressed*")
        {
    
            if ($_.length -lt $driveinfo.BlockSize -and $_.length -ne 0)
            {
                $driveinfo.BlockSize
            }
            else
            {
                [FileInfo]::GetCompressedFileSize($_.fullname)
            }
        }
        else
        {
            if ($_.length -lt $driveinfo.BlockSize -and $_.length -ne 0)
            {
                $driveinfo.BlockSize
            }
            else
            {
                ([math]::ceiling($_.length/$driveinfo.BlockSize))*$driveinfo.BlockSize
            }
        }
    }|Measure -sum).sum
    
    $sizeondisk
    

    稀疏文件的更新:

    让我们看看这个版本是否适用于稀疏文件,在前面代码的末尾添加这段代码,保持其他所有内容相同:

    $sparsesize = ($files | %{      
        if ($_.length -lt $driveinfo.BlockSize -and $_.length -ne 0)
        {
            $driveinfo.BlockSize
        }
        else
        {
            $_.fullname
            [FileInfo]::GetCompressedFileSize($_.fullname)
        }
    }|Measure -sum).sum
    
    $sparsesize
    

    来源:

    Understanding NTFS compression

    Help querying files to return SIZE on DISK

    Size of compressed files (in French)

    How to get the actual size-on-disk of a file from PowerShell?

    Default cluster size for NTFS, FAT, and exFAT

答案 1 :(得分:0)

出于某种原因,我在稀疏文件代码段中遇到了某些值是字符串而不是数字的错误。

然而,当我拿出&#34; 。$ _全名&#34;从下面

$sparsesize = ($files | %{      
if ($_.length -lt $driveinfo.BlockSize -and $_.length -ne 0)
{
    $driveinfo.BlockSize
}
else
{
    $_.fullname
    [FileInfo]::GetCompressedFileSize($_.fullname)
}
}|Measure -sum).sum

$sparsesize

并将其更改为

$sparsesize = ($files | %{      
if ($_.length -lt $driveinfo.BlockSize -and $_.length -ne 0)
{
    $driveinfo.BlockSize
}
else
{
    [FileInfo]::GetCompressedFileSize($_.fullname)
}
}|Measure -sum).sum

$sparsesize

然后它返回一个数值。