Найти место в каталоге на диске с помощью powershell

Я хотел знать размер своих различных подкаталогов, поэтому я следовал указаниям Получение размеров каталога powershell и Отображать структуру каталогов в powershell и некоторых других здесь, в SO, и где-то еще. Эти функции работают хорошо, за исключением того, что я хочу знать, сколько места на диске занимают некоторые частично синхронизированные папки (например, у меня есть папка в Skydrive, и только некоторые из ее подпапок доступны онлайн). Когда я вызываю любую функцию, они сообщают о размере папки как если бы она находилась на диске, а не о фактическом использовании диска. Если я щелкну папку правой кнопкой мыши и проверю ее свойства, я ясно увижу разницу между size и size in disk.

Я пробовал с Sort-Object -Property Size и Sort-Object -Property Length переключаться на любую функцию (в основном на основе функции Get-ChildItem), но обе они возвращают размер, а не размер на диске.

Я предполагаю, что есть простой переключатель, позволяющий учитывать только фактическое использование диска, а не общий размер, но я совершенно не понимаю, как этого добиться. Любые выводы очень ценятся!

Спасибо,


person PavoDive    schedule 15.12.2014    source источник
comment
Вы можете найти это полезным: stackoverflow.com/questions/16178919/   -  person shree.pat18    schedule 15.12.2014
comment
Пожалуйста, прочитайте это для размера в информации о диске stackoverflow.com/questions/13959228/   -  person hysh_00    schedule 15.12.2014


Ответы (2)


Размер на диске — это фактический размер, занимаемый вашими файлами на диске, в зависимости от размера кластера (или единицы распределения), который в большинстве случаев составляет 4 КБ, но не всегда. Это зависит от формата файла и от того, как он был отформатирован.

Пока файлы не сжаты, нужно выяснить, сколько фрагментов кластеров необходимо для размещения каждого файла. Имейте в виду, что если файл меньше размера кластера, он займет одну единицу распределения.

Если файл сжат, информацию нелегко получить, и ее необходимо получить через API.

Следующий код разделен на 3 основных раздела:

  1. Он определяет тип, используемый для доступа к функции GetCompressedFileSizeAPI в kernel.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 на DISK

Размер сжатых файлов (на французском языке)

Как получить фактический размер -на диск файла из PowerShell?

Размер кластера по умолчанию для NTFS, FAT и exFAT

person Micky Balladelli    schedule 15.12.2014
comment
Спасибо за ваш интерес и помощь. Я запустил ваш код в папке на моем скайдрайве, файлы которой я сделал доступными только в Интернете. Его нормальный размер составляет около 2,5 ГБ, и когда я щелкаю его правой кнопкой мыши, в свойствах отображается 1,4 МБ на диске. Ваш код точно сообщает о 2,5 ГБ (очень близко к коду, на который я ссылался в вопросе), и делает это, даже если я переведу компьютер в режим полета (файлы не будут доступны в этом сценарии). Что я делаю не так? - person PavoDive; 15.12.2014
comment
Размер 2,5 ГБ, а размер на диске 1,4 МБ? Что-то не так, интересно, использует ли он разреженные файлы, и в этом случае этот код не сможет его увидеть. - person Micky Balladelli; 15.12.2014
comment
Смотрите этот скриншот. Хотя он на испанском. dropbox.com/s/lz0o1wp4nv2tuqj/size%20on% 20disk.png?dl=0 Я думаю, причина в том, что большинство файлов доступны только онлайн ?? - person PavoDive; 15.12.2014
comment
Да, выглядит как разреженный файл, большая часть незначимых данных не размещена на диске. В следующей ссылке упоминается, что GetCompressedFileSize можно использовать для определения размера. Мы используем это для сжатого кода, так что, возможно, вы сможете его принудительно использовать. msdn.microsoft.com/ en-us/library/windows/desktop/ - person Micky Balladelli; 15.12.2014
comment
Я обновил ответ новым блоком кода, который должен иметь дело с разреженным размером файлов. - person Micky Balladelli; 15.12.2014
comment
Затем он выдает исключение: (говорит, что у системы нет доступа к файлу, что, безусловно, есть) Excepción al llamar a "GetCompressedFileSize" con los argumentos "1": "El sistema no tiene acceso al archivo" En C:\Users\giova_000\Desktop\sizeod.ps1: 41 Carácter: 9 + [FileInfo]::GetCompressedFileSize($_.fullname) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : Win32Exception - person PavoDive; 15.12.2014
comment
Однако не указано, какой именно файл. В нем говорится, что скрипт sizeod.ps1 в строке 41 не может получить доступ к $_.fullname, было бы хорошо вывести это имя файла, чтобы вы могли проверить, есть ли у вас доступ. Я обновлю код - person Micky Balladelli; 15.12.2014

По какой-то причине я сталкивался с ошибками в отношении того, что определенные значения являются строками, а не числовыми в фрагменте кода разреженного файла.

Однако я заметил, когда вынул "$_.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

Затем он вернул числовое значение.

person Bejellio    schedule 17.03.2016