PowerShell Get-DiskUsage CmdLet:如何从不同的驱动器/目录列出? [英] PowerShell Get-DiskUsage CmdLet: how to list from a different drive/directory?

查看:56
本文介绍了PowerShell Get-DiskUsage CmdLet:如何从不同的驱动器/目录列出?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 PowerShell 的相对新手,想了解更多关于函数、CmdLet 和人类可读值的信息.通常用于学习新事物,看看别人做得很好.

I'm a relative newbie on PowerShell, wanted to know a bit more about functions, CmdLet and human readable values. Usually for learning new things, looking at what others do works well.

所以我去找了Get-DiskUsage CmdLet的来源.

So I went looking and bumped into the source for a Get-DiskUsage CmdLet.

我可以.将其导入 PowerShell,然后调用该函数.

I can . source this into PowerShell, then call the function.

不知何故,无论我怎么称呼它,它总是使用当前目录来获取结果.

Somehow, it always uses the current directory for getting the results no matter how I call it.

我错过了什么,它不会采用给定的 -Path 参数?

What am I missing that it will not take the given -Path parameter?

PS D:\bin> . .\DiskUsage.ps1
PS D:\bin> Get-DiskUsage -Path D:\ -h

Size Folder
---- ------
405M


PS D:\bin> Get-DiskUsage -Path C:\ -h

Size Folder
---- ------
405M


PS D:\bin> C:
PS C:\> Get-DiskUsage -Path C:\ -h

Size Folder
---- ------
 18G


PS C:\>

脚本输出不正确,因为这是 SysInternals DiskUsage 工具 du 显示:

The script output is not right, as this is what the SysInternals DiskUsage tool du shows:

D:\bin>du C:\

Du v1.4 - report directory disk usage
Copyright (C) 2005-2011 Mark Russinovich
Sysinternals - www.sysinternals.com

Files:        93367
Directories:  22541
Size:         21.817.875.778 bytes
Size on disk: 22.127.992.832 bytes


D:\bin>du D:\

Du v1.4 - report directory disk usage
Copyright (C) 2005-2011 Mark Russinovich
Sysinternals - www.sysinternals.com

Files:        132832
Directories:  15125
Size:         130.137.231.457 bytes
Size on disk: 54.992.396.288 bytes


D:\bin>du D:\bin

Du v1.4 - report directory disk usage
Copyright (C) 2005-2011 Mark Russinovich
Sysinternals - www.sysinternals.com

Files:        3118
Directories:  222
Size:         424.866.944 bytes
Size on disk: 288.858.112 bytes

推荐答案

Get-DiscUsage C:\ # NOT RECOMMENDED

Get-DiskUsage -Path C:\Users\JBennett\SkyDrive\WindowsPowershell\Scripts\IO\

Size Folder
---- ------
223424B C:\Users\JBennett\SkyDrive\WindowsPowershell\Scripts\IO\DU

无论哪种方式都适合我(在第一次点源脚本之后,如您所说).

Either way works for me (after first dot-sourcing the script, as you said).

我不得不说,我不会使用它......它正在使用 PowerShell 进行递归目录扫描,生成(数千个)DirectoryInfo 对象,然后它在每个文件夹上进行另一个递归目录扫描,创建一个新对象和总结属性......它非常慢,与du.exe相比会消耗大量内存和IO

I have to say though, I wouldn't use that... It's doing a recursive directory scan with PowerShell, generating (thousands of) DirectoryInfo objects and then it's doing ANOTHER recursive directory scan ON EACH FOLDER, creating a new object and summing properties ... It's hideously slow, and will consume a lot of memory and IO compared to du.exe

当您希望递归地获得树中每个文件夹的 SIZE 时,算法正确的方法不涉及 Get-ChildItem 上的 -Recurse 标志.你可以这样做:

When you want the SIZE of every folder in a tree, recursively, the algorithmically correct way to do that DOES NOT involve the -Recurse flag on Get-ChildItem. You might do something like this:

function Get-Size {
  #.Synopsis
  #  Calculate the size of a folder on disk
  #.Description
  #  Recursively calculate the size of a folder on disk,
  #  outputting it's size, and that of all it's children,
  #  and optionally, all of their children
  param(
    [string]$root,
    # Show the size for each descendant recursively (otherwise, only immediate children)
    [switch]$recurse
  )
  # Get the full canonical FileSystem path:
  $root = Convert-Path $root

  $size = 0
  $files = 0
  $folders = 0

  $items = Get-ChildItem $root
  foreach($item in $items) {
    if($item.PSIsContainer) {
      # Call myself recursively to calculate subfolder size
      # Since we're streaming output as we go, 
      #   we only use the last output of a recursive call
      #   because that's the summary object
      if($recurse) {
        Get-Size $item.FullName | Tee-Object -Variable subItems
        $subItem = $subItems[-1]
      } else {
        $subItem = Get-Size $item.FullName | Select -Last 1
      }

      # The (recursive) size of all subfolders gets added
      $size += $subItem.Size
      $folders += $subItem.Folders + 1
      $files += $subItem.Files
      Write-Output $subItem
    } else {
      $files += 1
      $size += $item.Length
    }
  }

  # in PS3, use the CustomObject trick to control the output order
  if($PSVersionTable.PSVersion -ge "3.0") {
    [PSCustomObject]@{ 
      Folders = $folders
      Files = $Files
      Size = $size
      Name = $root
    }
  } else {
    New-Object PSObject -Property @{ 
      Folders = $folders
      Files = $Files
      Size = $size
      Name = $root
    }
  }
}

这样,您就不会多次列出任何内容.不利的一面是您必须自己添加所有内容,因为您不能只使用 Measure-Object.

That way, you're not listing anything more than once. The down side is that you have to add everything up yourself, because you can't just use Measure-Object.

OP 中引用的脚本实际上列出了每个项目,无论它有多深.也就是说,如果一个文件在 C:\Users\Jaykul\Documents\WindowsPowerShell\Scripts ... 它将显示在每个父文件夹的 gci -recurse 中——如果你调用五次根上的脚本.

The script referenced in the OP actually lists every item however many times it is deep. That is, if a file is in C:\Users\Jaykul\Documents\WindowsPowerShell\Scripts ... it will show up in the gci -recurse for each parent folder -- five times if you call the script on the root.

当然,您仍在为每个文件创建一个 FileInfo 并为每个目录创建一个 DirectoryInfo,加上我在脚本中手动创建的摘要 PSObject,所以即使这几乎一样快作为 du.exe,它会对内存产生更大的影响.

Of course, you're still creating a FileInfo for every file and a DirectoryInfo for every directory, plus the summary PSObject I created by hand in the script, so even if this was nearly as fast as du.exe, it would have significantly more impact on memory.

然而,这是 PowerShell 固有的权衡:做事情更容易……因为我们有重物.我们很乐意用易用性换取内存,有时甚至会降低性能.也就是说:是的,du.exe 会更快,但它是一个必须有人专门为一个目的而编写的一招小马.如果您只想运行它并读取输出,它仍然是最好的方法.但是它会产生文本输出,如果您想在脚本中使用它的输出,您必须对其进行解析,而且很难将该信息作为整个仪表板式监控脚本的输出的一部分来收集...

However, that's the inherent trade-off in PowerShell: it's easier to do things... because we have heavy objects. We gladly trade ease of use for memory, and sometimes even a performance hit. That is to say: yes, du.exe will be faster, but it's a one-trick pony that someone had to specifically write for one purpose. It's still the best way, if all you wanted to do is run it and read the output. But it produces text output you have to parse if you want to use it's output in a script, and it's really hard to collect that information as one part of the output of an overall dashboard-style monitoring script...

这篇关于PowerShell Get-DiskUsage CmdLet:如何从不同的驱动器/目录列出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆