2014-12-15 6 views
1

Мне хотелось узнать размер моих разных подкаталогов, поэтому я следил за показаниями Getting Directory sizes powershell и Display directory structure in powershell и некоторыми другими здесь, в SO и где-то еще. Эти функции работают хорошо, за исключением того, что я хочу знать пространство, в котором некоторые из частично синхронизированы. папки занимают на диске (например, у меня есть папка в Skydrive, и только некоторые ее подпапки доступны в Интернете). Когда я вызываю любую функцию, они сообщают размер папки , как если бы она находилась на диске, а не на фактическом использовании диска. Если я щелкнул правой кнопкой мыши папку и проверил ее свойства, я ясно вижу, что существует разница между size и size in disk.Найти место на диске с помощью powershell

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

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

Спасибо,

+0

Вы можете найти это полезным: http://stackoverflow.com/questions/16178919/powershell-get-diskusage-cmdlet-how-to-list-from-a-different-drive-directory –

+0

Прочтите это для " размер на диске "info http://stackoverflow.com/questions/13959228/file-size-actual-number-of-bytes-used-on-disk-not-allocated –

ответ

2

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

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

Если файл сжат, информация нелегко доступна и должна быть извлечена через 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 

UPDATE для разреженных файлов:

Давайте посмотрим, если эта версия работает с разреженными файлами, добавьте этот блок кода в конце предыдущего кода, держать все остальное то же самое:

$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

+0

Спасибо за ваш интерес и помощь. Я запустил ваш код в папке в моем skydrive, чьи файлы я установил в «только онлайн». Его нормальный размер составляет около 2,5 ГБ, а когда я его правой кнопкой, по свойствам он сообщает 1.4 МБ «на диске». Ваш код точно сообщает о 2,5 ГБ (очень близко к коду, на который я ссылался в вопросе), и делает это, даже если я поставлю компьютер в плоском режиме (файлы не будут доступны в этом сценарии). Что я делаю не так? – PavoDive

+0

Размер 2,5 ГБ, а размер на диске - 1,4 МБ? Что-то не так, интересно, использует ли он разреженные файлы, и в этом случае этот код не сможет его увидеть. –

+0

Посмотрите на скриншот. Однако на испанском языке. https://www.dropbox.com/s/lz0o1wp4nv2tuqj/size%20on%20disk.png?dl=0 Я думаю, что причина в том, что большинство файлов установлены как «доступные только в Интернете»? – PavoDive

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 

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