这个powershell程序中最大的文件? [关闭]
Posted
技术标签:
【中文标题】这个powershell程序中最大的文件? [关闭]【英文标题】:Biggest file in this powershell program? [closed] 【发布时间】:2014-04-16 15:16:00 【问题描述】:我需要两个简单的东西,我的程序要求用户输入一个目录,我需要一种方法,如果没有输入任何内容,则使用默认目录。
其次,从给定的目录中找到最大的文件。
有人告诉我要使用:
Get-ChildItem c:\temp | Sort Length -desc | Select-Object -First 1
但这对我来说也可能是中文。我只知道Java。我得到了它应该做的事情,但它在我的代码中什么也没做:
$a = Read-Host “Enter directory”
function Get-Size
param ($Path)
$Size = 0
foreach ($Folder in (Get-ChildItem $Path))
if ($Folder.PSIsContainer)
Get-Size $Folder.FullName
else
$Size += $Folder.Length
New-Object PSObject -Property @'Size in KB'=$Size/100; 'Folder'=$Path
Write-Host "Disk space use (in KB) for each subdirectory:"
Get-Size $a
【问题讨论】:
如果您不了解 powershell 而您需要它,那么请学习 powershell!你已经得到了执行它的命令,那么你试试看会发生什么?我不是想无礼,但试图让我们为你做这项工作的人让我感到沮丧。这不是 SO 的目的。 嗯...今天的人群很激烈。 :) 我经常对 gimme-teh-codez 问题投赞成票,但这看起来更像是一个正在尝试学习和让事情自己工作但感到困惑的人,而不是正在尝试的人让其他人为他做这项工作。让我恼火的是那些只描述一组需求并问“你是怎么做到的?”,然后坐等其他人来编写代码的人。至少这个人试了一下,发布了他的代码,并展示了他一直在努力寻找解决方案的证据。 说你不明白就足够了。中文(粤语和普通话)对很多人来说是可以理解的。 【参考方案1】:好吧,您的代码存在一些问题,但首先我会回答您提出的问题。
1.向用户询问目录,如果没有输入则使用默认目录
要让函数对任何参数使用默认值,只需在参数声明的末尾添加= defaultvalue
。在这种情况下,
param (
$Path = 'C:\My\Default\Directory'
)
如果不希望函数使用默认目录,但希望脚本在提示用户时分配默认目录,可以这样:
if (! ($a = Read-Host 'Enter directory'))
$a = 'C:\My\Default\Directory'
if 条件执行$a = Read-Host 'Enter directory'
,如果用户没有输入任何内容(赋值语句计算分配给变量的值,空字符串是假值,所以如果用户在没有提供值的情况下点击 Enter,(! ($a = Read-Host 'Enter directory'))
为真)。
2。查找目录中的最大值
给你的命令有效:
Get-ChildItem c:\temp | Sort Length -desc | Select-Object -First 1
您说它在您的代码中没有任何作用,但我什至没有在您的代码中看到它。如果您显示尝试添加它的位置/方式,我将能够告诉您为什么它似乎什么也没做。这可能与您尝试使用结果的方式有关。现在我可以解释它是如何工作的。
Get-ChildItem C:\Temp |
当然会列出 C:\Temp 的内容,并将结果(代表目录中每个项目的 FileInfo 对象)发送到管道。
Sort Length -desc |
按降序对结果进行排序,并将排序后的结果发送到管道中。 Sort 是 Sort-Object 的简写,Length 是包含文件大小(以字节为单位)的 FileInfo 对象的属性,- desc是-Descending的缩写。
Select-Object -First 1
从结果中选择第一项。由于它们是按文件大小降序排列的,因此第一项是表示最大文件的 FileInfo 对象。
您的代码中与问题没有直接关系的其他一些问题
PowerShell 旨在与管道一起使用。而不是
foreach ($Folder in (Get-ChildItem $Path))
使用
Get-ChildItem $Path | %
在打字和处理方面都更加高效。 % 是 ForEach-Object 的缩写(不与 foreach 循环相同;它是用于管道的过滤器,通常运行效率更高)。
$Size/100
不会给你以 KB 为单位的大小,因为 1 KB 是 1024 字节,但有一个内置的速记:
$Size / 1KB.
你也可以使用1MB
、1GB
、1TB
、1PB
(抱歉,目前还没有1EB
,但我相信5-10年后不仅会有一个,它可能会非常频繁地使用)。请注意,您可以更改系数,但不能省略(/ 2GB
除以 2 GB,但没有 1
的 / GB
是语法错误)
无需使用递归函数来执行此操作。 PowerShell 具有用于递归遍历目录树和汇总结果的内置工具。这是一个显示如何做到这一点的版本,并结合了上面提出的建议:
function Get-Size
param (
$Path = 'C:\My\Default\Directory'
)
Get-ChildItem $Path -Recurse | ?$_.PSIsContainer | %
$Size = (Get-ChildItem $_.FullName | Measure-Object Length -Sum -ea SilentlyContinue).Sum
New-Object PSObject -Property @'Size in KB' = ($Size / 1KB); 'Folder' = $_.FullName
输出会相当混乱,因此您可能希望将结果通过管道传送到 Format-Table。我认为最好在调用函数时进行格式化,而不是将其包含在函数定义本身中。这将以您可能想要的顺序为您提供属性,大小右对齐并固定为小数点后两位:
Get-Size $a | Format-Table @Name = 'Size in KB'; Expression = "0:N2" -f $_.'Size in KB'; Align = 'right', ' ', Folder -AutoSize
【讨论】:
很好解释。不过,我会将-Recurse
添加到Get-ChildItem
,因为 OP 的代码 sn-p 似乎递归到子文件夹中。
我没有走那条路,因为我可以发誓我上周读到管道到 foreach 的性能更差。我希望我已经为参考添加了书签。
@AnsgarWiechers 好点。实际上,我在要添加到第三个要点的代码中添加了 -Recurse 开关,但我没有发布该代码,因为在我完成编辑之前发布了另一个基本相同的答案。在第一个要点中,我想让事情变得简单,以便只专注于展示如何使用管道语法来替换 foreach 循环。但你是对的,因为我建议他将我的代码与其他答案中的代码结合起来,如果没有 -Recurse,它就无法工作。我将把我的组合代码添加到第三个项目符号中以使事情更清楚。
@TheMadTechnician 很久以前我确实读过一些博客文章,声称 foreach 循环更有效(可能和你看到的一样),有一段时间我在写由于那个糟糕的建议,糟糕的代码。但后来我在多个其他来源中读到了完全相反的内容,其中一些在解释 为什么 管道版本更有效时进入了更多技术深度,所以我使用我们的朋友 Measure-Object
进行了一系列实验,这表明到 Foreach-Object 的管道几乎总是更有效,有时甚至更有效。
我想这是一个更大的话题,而不是一个比另一个更有效率的话题。 % 似乎使用较少的内存,但 foreach 循环实际上通常更快,有时甚至更快。在我进行更全面的调查之前,我将撤回使用管道的建议。至于在哪里问,我认为一方面它与 SO 相关,因为它是一个关于编码的具体、客观的问题,但另一方面,对于问答形式来说,它可能是一个太多的讨论问题。也许这是programmers.stackexchange.com,或者chat?【参考方案2】:
首先,Frode F. 说的是对的。如果您需要使用 PowerShell,请学习 PowerShell。来到这里并说明您所做的事情是“我是一个 java 人,我不懂 PowerShell,请为我修复它,因为我要么太忙而无法弄清楚它,要么它就在我下面”。要求我们纠正您似乎没有花时间尝试和理解的事情是滥用我们免费提供的服务和善意。我现在就离开我的肥皂盒来帮助你。
您的请求和您的代码说明了两件截然不同的事情。您的脚本获取文件夹中所有内容的总大小,并递归地为所有子文件夹执行此操作。您的请求是在该文件夹中查找最大的文件。
实际上,您有 2 个请求。默认文件夹的设置很简单。如果没有给出路径,则设置默认值是正确设置参数的简单问题。如果您在 Param 部分中为您的参数设置了一个值,则如果未输入任何值,则该值将被视为默认值。这样做会为您解决这个问题:
Function Get-Size
Param ($Path="$env:USERPROFILE\Desktop")
<code goes here>
这会将默认设置为当前用户的桌面文件夹。
至于获得最大的文件,你得到的代码会做到这一点。让我解释一下。
Get-ChildItem $path
提取$path
的目录列表。管道 (|
) 将该信息发送到下一个命令,即Sort
。
Sort Length -desc
按长度(实际上是文件大小)对第一个命令的结果进行降序排序。这将通过管道传送到Select
。
Select-Object -first 1
选择前 1 个结果(您可以使用 -first 3
选择前 3 个结果或不选择)。由于它们已经按降序排列,因此它会选择指定路径中的最大文件。
请注意,这不会递归运行。要使其搜索所有文件夹并返回最大的文件,请将-recurse
开关添加到Get-ChildItem
命令。
至于你的脚本,嗯,它做了它打算做的事情。它获取每个文件夹和子文件夹的完整大小并报告回来。它的工作方式有点笨拙,但它很实用。至于我,我认为我会做更多这样的事情:
Function Get-Size
Param ([Parameter(ValueFromPipeline=$True)]
$Path="$env:USERPROFILE\Desktop")
ForEach ($Folder in (Get-ChildItem $Path -recurse|?$_.PSIsContainer))
$Size = (Get-ChildItem $Folder.FullName | Measure-Object -property length -sum -ea SilentlyContinue)
New-Object PSObject -Property @'Size in KB'="0:N2" -f ($Size.sum/1KB) +" KB"; 'Folder'=$Folder.FullName
Read-Host "Enter a path" | Get-Size
【讨论】:
以上是关于这个powershell程序中最大的文件? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
如何使程序仅在使用批处理或 powershell 有 Internet 连接时运行? [关闭]