[玩转系统] 我的 PowerShell 存储桶中有一个文件
作者:精品下载站 日期:2024-12-14 08:04:19 浏览:12 分类:玩电脑
我的 PowerShell 存储桶中有一个文件
如果有一项任务是我从未停止过的,那就是查找文件。我不断创造新的方法来组织文件并以有意义的格式显示它们。当然,PowerShell 是完成此任务的绝佳工具。 Get-ChildItem 显然是正确的起点。该 cmdlet 可以很好地仅从文件夹中获取文件,并且我可以使用通配符按名称和扩展名进行基本的早期过滤。但我最近的任务是按日期组织文件,并且由于 Get-ChildItem 的幕后工作方式,我将需要借助Where-Object 进行后期过滤。这并没有什么问题。但如果这是我可能重复的任务,那么 PowerShell 函数就在我的绘图板上。我的目标是创建一个函数来显示按老化存储桶(例如 1 周或 6 个月)分组的文件。尽管我主要关心基于上次写入时间的年龄,但我(或您)可能需要根据创建时间来确定年龄。让我们来编码。
建立一个清单
我的函数将从 Get-Childitem 获取管道输入。但是,因为我要对文件进行排序和分组,所以在我的函数处理完 Get-ChildItem 中的所有文件之前我无法执行此操作。当它们通过管道时,我需要暂时存储它们。我可以使用一个数组对象并将每个管道对象添加到其中。我的代码可能看起来像这样。
Begin {
$files = @()
}
Process {
$files += $inputobject
}
End {
$files | Sort-Object -property LastWriteTime ...
}
从技术上讲,这种方法没有任何问题,而且我已经使用它很多年了。但最近,我开始转向通用列表。具体来说是一个 [System.Collections.Generic.list[]] 对象。原因是,当您添加到数组时,每次添加元素时,数组都会被擦除并重建。对于少量物品来说,这没有问题。但我可能会处理数千个文件。为了易用性,将会有轻微的性能权衡。我在 3 秒多一点的时间里向数组添加了近 9000 个文件。使用通用列表只需要不到一秒钟的时间。
在函数的 Begin 块中,我可以像这样定义集合对象:
$list = [system.Collections.Generic.list[system.io.fileinfo]]::new()
但是,我将使用脚本技术来简化该语法。在定义函数的 .ps1 文件中,我将在函数之前插入一条 using 语句。
Using namespace System.Collections.Generic
现在在 Begin 块中,我的定义要简单得多:
$list = [List[System.IO.FileInfo]]::new()
您通常会告诉 PowerShell 什么类型的对象将进入您的列表。就我而言,我知道它将是 System.IO.FileInfo 对象。如果您不确定或想要混合对象,您可以简单地使用“对象”。
列表对象有许多方法,我不会在这里介绍。在“进程”块中,我将每个文件添加到列表中。
$list.Add($FilePath)
当我到达 End 块时, $list 将包含通过管道传输到我的函数中的所有文件。现在我可以施展我的水桶魔法了。
年龄分组
我必须决定我想要什么样的陈年桶。我是按照年、月、天数来决定的。我将用一个参数来控制它。
[Parameter(HelpMessage = "How do you want the files organized? The default is Month.")]
[ValidateNotNullOrEmpty()]
[ValidateSet("Month","Year","Days")]
[string]$GroupBy = "Month"
我还需要控制我所做的衰老决定的基础。
[Parameter(HelpMessage = "Specify if grouping by the file's CreationTime or LastWriteTime property. The default is LastWriteTime.")]
[ValidateSet("CreationTime","LastWritetime")]
[ValidateNotNullOrEmpty()]
[string]$Property = "LastWriteTime",
对于列表中的每个文件,我需要添加一个指示其年龄组的属性。我知道我要向文件对象添加一个属性。
$file | Add-Member -MemberType NoteProperty -Name AgeGroup -Value $value
该值将根据分组桶计算。如果我想按年份分组,对于每个文件,我将运行以下代码:
$value = $file.$property.year
$sort = "AgeGroup"
$sort 变量将在函数末尾使用以帮助格式化输出。对于月份分组,我需要月份和年份。我还需要将值转换为 DateTime 对象,以便它可以正确排序。 $Property 将为 CreationTime 或 LastWriteTime。
$value = "$($file.$property.month)/$($file.$property.year)"
$sort = {$_.AgeGroup -as [datetime]}
自定义属性自定义值
按天数分组是最棘手的步骤。我决定定义一组存储桶名称,例如 OneWeek 和 SixMonth。然而,这意味着排序将根据字符串值进行,而这是不准确的。我的解决方案是在我的函数文件中定义一个枚举。
Enum FileAge {
YearPlus
Year
NineMonth
SixMonth
ThreeMonth
OneMonth
OneWeek
OneDay
}
为什么?因为在 Enum 中,每个值实际上都有一个从 0 开始的数值。尽管我使用字符串来指示老化存储桶,但当我排序时,它将位于隐式数值上。通过这个枚举,我可以根据总天数分配一个值。
$age = New-TimeSpan -start $file.$property -end $now
$value = switch ($age.totaldays -as [int]) {
{$_ -ge 365} {[FileAge]::YearPlus ; break}
{$_ -gt 270 -AND $_ -lt 365 }{[FileAge]::Year;break}
{$_ -gt 180 -AND $_ -le 270 }{[FileAge]::NineMonth;break}
{$_ -gt 90 -AND $_ -le 180} {[FileAge]::SixMonth;break}
{$_ -gt 30 -AND $_ -le 90} {[FileAge]::ThreeMonth;break}
{$_ -gt 7 -AND $_ -le 30} {[FileAge]::OneMonth;break}
{$_ -gt 1 -And $_ -le 7} {[FileAge]::OneWeek;break}
{$_ -le 1} {[FileAge]::OneDay;break}
}
$sort = "AgeGroup"
我可以创建一个自定义对象,甚至使用 PowerShell 类。但我很高兴利用 System.IO.FileInfo 类型。但是,默认格式对我的自定义属性一无所知。我知道我想要创建自己的格式,因此我需要插入新的类型名称。
$file.psobject.TypeNames.insert(0,"FileAgingInfo")
提前计划,我知道我将在自定义格式中使用分组,这意味着需要对对象进行排序。通常,我会离开函数进行排序,但在这种情况下,我需要它。
$list | Sort-Object -Property $sort,DirectoryName,$property,Name
我首先对 $sort 变量进行排序,然后是目录名,然后是 CreationTime 或 LastWriteTime 属性,最后是文件名。
这是完整的功能:
#requires -version 5.1
#declaring a namespace here makes the code simpler later on
Using namespace System.Collections.Generic
#define an enumeration that will be used in a new custom property
Enum FileAge {
YearPlus
Year
NineMonth
SixMonth
ThreeMonth
OneMonth
OneWeek
OneDay
}
Function Get-FileAgeGroup {
[cmdletbinding()]
[alias("gfa")]
[OutputType("FileAgingInfo")]
Param(
[Parameter(Mandatory,Position=0,ValueFromPipeline,HelpMessage = "The path to a file. If you pipe from a Get-ChildItem command, be sure to use the -File parameter.")]
[ValidateNotNullOrEmpty()]
[System.IO.FileInfo]$FilePath,
[Parameter(HelpMessage = "Specify if grouping by the file's CreationTime or LastWriteTime property. The default is LastWriteTime.")]
[ValidateSet("CreationTime","LastWritetime")]
[ValidateNotNullOrEmpty()]
[string]$Property = "LastWriteTime",
[Parameter(HelpMessage = "How do you want the files organized? The default is Month.")]
[ValidateNotNullOrEmpty()]
[ValidateSet("Month","Year","Days")]
[string]$GroupBy = "Month"
)
Begin {
Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting $($myinvocation.mycommand)"
Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Grouping by $GroupBy on the $Property property"
#initialize a list to contain all piped in files
#this code is shorter because of the Using statement at the beginning of this file
$list = [List[System.IO.FileInfo]]::new()
#get a static value for now
$now = Get-Date
} #begin
Process {
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Adding $FilePath"
#add each file to the list
$list.Add($FilePath)
} #process
End {
#now process all the files and add aging properties
Write-Verbose "[$((Get-Date).TimeofDay) END ] Sorting $($list.count) files"
#add custom properties based on the age grouping
foreach ($file in $list) {
switch ($GroupBy) {
"Month" {
$value = "$($file.$property.month)/$($file.$property.year)"
$sort = {$_.AgeGroup -as [datetime]}
}
"Year" {
$value = $file.$property.year
$sort = "AgeGroup"
}
"Days" {
$age = New-TimeSpan -start $file.$property -end $now
$value = switch ($age.totaldays -as [int]) {
{$_ -ge 365} {[FileAge]::YearPlus ; break}
{$_ -gt 270 -AND $_ -lt 365 }{[FileAge]::Year;break}
{$_ -gt 180 -AND $_ -le 270 }{[FileAge]::NineMonth;break}
{$_ -gt 90 -AND $_ -le 180} {[FileAge]::SixMonth;break}
{$_ -gt 30 -AND $_ -le 90} {[FileAge]::ThreeMonth;break}
{$_ -gt 7 -AND $_ -le 30} {[FileAge]::OneMonth;break}
{$_ -gt 1 -And $_ -le 7} {[FileAge]::OneWeek;break}
{$_ -le 1} {[FileAge]::OneDay;break}
}
$sort = "AgeGroup"
}
} #switch
#add a custom property to each file object
$file | Add-Member -MemberType NoteProperty -Name AgeGroup -Value $value
#insert a custom type name which will be used by the custom format file
$file.psobject.TypeNames.insert(0,"FileAgingInfo")
} #foreach file
#write the results to the pipeline. Sorting results so that the default
#formatting will be displayed properly
$list | Sort-Object -Property $sort,DirectoryName,$property,Name
Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending $($myinvocation.mycommand)"
} #end
} #close Get-FileAgeGroup
格式化输出
这项工作的重点是让我可以轻松地查看按年龄分组的文件,如下所示:
这就是为什么我需要自定义类型名称和预排序输出。我使用 New-PSFormatXML 创建自定义格式 ps1xml 文件。
<!--
Format type data generated 09/17/2021 11:54:13 by PROSPERO\Jeff
This file was created using the New-PSFormatXML command that is part
of the PSScriptTools module.
https://github.com/jdhitsolutions/PSScriptTools
-->
<Configuration>
<ViewDefinitions>
<View>
<!--Created 09/17/2021 11:54:13 by PROSPERO\Jeff-->
<Name>default</Name>
<ViewSelectedBy>
<TypeName>FileAgingInfo</TypeName>
</ViewSelectedBy>
<GroupBy>
<!--
You can also use a scriptblock to define a custom property name.
You must have a Label tag.
<ScriptBlock>$_.machinename.toUpper()</ScriptBlock>
<Label>Computername</Label>
Use <Label> to set the displayed value.
-->
<PropertyName>AgeGroup</PropertyName>
<Label>AgeGroup</Label>
</GroupBy>
<TableControl>
<!--Delete the AutoSize node if you want to use the defined widths.-->
<AutoSize />
<TableHeaders>
<TableColumnHeader>
<Label>Directory</Label>
<Width>16</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>Created</Label>
<Width>24</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>Modified</Label>
<Width>23</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>Length</Label>
<Width>11</Width>
<Alignment>right</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>Name</Label>
<Width>10</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
</TableHeaders>
<TableRowEntries>
<TableRowEntry>
<TableColumnItems>
<!--
By default the entries use property names, but you can replace them with scriptblocks.
<ScriptBlock>$_.foo /1mb -as [int]</ScriptBlock>
-->
<TableColumnItem>
<PropertyName>DirectoryName</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>CreationTime</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>LastWriteTime</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Length</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Name</PropertyName>
</TableColumnItem>
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
</ViewDefinitions>
</Configuration>
在 ps1 文件末尾,我将格式文件导入到我的 PowerShell 会话中。
Update-FormatData $psscriptroot\FileAge.format.ps1xml
我现在只有一个视图。
因为我使用枚举,所以我的文件已正确排序,并且我得到了有意义的输出。我可能需要稍微调整一下格式文件。
或者我可以调整我的 PowerShell 表达式。
与我的许多帖子一样,最终结果并不像我用来实现目标的技术那么重要。欢迎提出意见和问题。
猜你还喜欢
- 03-30 [玩转系统] 如何用批处理实现关机,注销,重启和锁定计算机
- 02-14 [系统故障] Win10下报错:该文件没有与之关联的应用来执行该操作
- 01-07 [系统问题] Win10--解决锁屏后会断网的问题
- 01-02 [系统技巧] Windows系统如何关闭防火墙保姆式教程,超详细
- 12-15 [玩转系统] 如何在 Windows 10 和 11 上允许多个 RDP 会话
- 12-15 [玩转系统] 查找 Exchange/Microsoft 365 中不活动(未使用)的通讯组列表
- 12-15 [玩转系统] 如何在 Windows 上安装远程服务器管理工具 (RSAT)
- 12-15 [玩转系统] 如何在 Windows 上重置组策略设置
- 12-15 [玩转系统] 如何获取计算机上的本地管理员列表?
- 12-15 [玩转系统] 在 Visual Studio Code 中连接到 MS SQL Server 数据库
- 12-15 [玩转系统] 如何降级 Windows Server 版本或许可证
- 12-15 [玩转系统] 如何允许非管理员用户在 Windows 中启动/停止服务
取消回复欢迎 你 发表评论:
- 精品推荐!
-
- 最新文章
- 热门文章
- 热评文章
[影视] 黑道中人 Alto Knights(2025)剧情 犯罪 历史 电影
[古装剧] [七侠五义][全75集][WEB-MP4/76G][国语无字][1080P][焦恩俊经典]
[实用软件] 虚拟手机号 电话 验证码 注册
[电视剧] 安眠书店/你 第五季 You Season 5 (2025) 【全10集】
[电视剧] 棋士(2025) 4K 1080P【全22集】悬疑 犯罪 王宝强 陈明昊
[软件合集] 25年6月5日 精选软件22个
[软件合集] 25年6月4日 精选软件36个
[短剧] 2025年06月04日 精选+付费短剧推荐33部
[短剧] 2025年06月03日 精选+付费短剧推荐25部
[软件合集] 25年6月3日 精选软件44个
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电视剧] 欢乐颂.5部全 (2016-2024)
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[影视] 【稀有资源】香港老片 艺坛照妖镜之96应召名册 (1996)
[剧集] 神经风云(2023)(完结).4K
[剧集] [BT] [TVB] [黑夜彩虹(2003)] [全21集] [粤语中字] [TV-RMVB]
[实用软件] 虚拟手机号 电话 验证码 注册
[资源] B站充电视频合集,包含多位重量级up主,全是大佬真金白银买来的~【99GB】
[影视] 内地绝版高清录像带 [mpg]
[书籍] 古今奇书禁书三教九流资料大合集 猎奇必备珍藏资源PDF版 1.14G
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电影] 美国队长4 4K原盘REMUX 杜比视界 内封简繁英双语字幕 49G
[电影] 死神来了(1-6)大合集!
[软件合集] 25年05月13日 精选软件16个
[精品软件] 25年05月15日 精选软件18个
[绝版资源] 南与北 第1-2季 合集 North and South (1985) /美国/豆瓣: 8.8[1080P][中文字幕]
[软件] 25年05月14日 精选软件57个
[短剧] 2025年05月14日 精选+付费短剧推荐39部
[短剧] 2025年05月15日 精选+付费短剧推荐36部
- 最新评论
-
- 热门tag