1

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

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

我想有一个简单的开关可以让它只考虑实际的磁盘使用情况,而不是总大小,但我完全不知道如何实现它。任何线索都非常感谢!

谢谢,

4

2 回答 2

2

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

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

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

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

  1. 它定义了一个用于访问GetCompressedFileSizeAPIkernel.dll 中的函数的类型。此函数将检索文件在磁盘上的压缩大小。
  2. 它使用 WMI 来确定给定的集群大小$path
  3. 它计算文件夹和子文件夹中文件的磁盘大小,$path具体取决于文件是否被压缩。

请注意,调用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

资料来源:

了解 NTFS 压缩

帮助查询文件返回 SIZE on DISK

压缩文件的大小(法语)

如何从 PowerShell 获取文件的实际磁盘大小?

NTFS、FAT 和 exFAT 的默认簇大小

于 2014-12-15T10:01:28.643 回答
0

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

但是,当我从下面取出“ $_.fullname”时,我注意到了

$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

然后它返回一个数值。

于 2016-03-17T14:31:46.443 回答