当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] PowerShell 脚本 • 使用重新设计的 PowerShell 获取 Git 大小

作者:精品下载站 日期:2024-12-14 07:54:30 浏览:17 分类:玩电脑

PowerShell 脚本 • 使用重新设计的 PowerShell 获取 Git 大小


几天前,我写了一篇关于设计 PowerShell 函数的经验,该函数报告隐藏的 .git 文件夹的大小。在该版本的函数中,我决定包含一个参数,该参数允许用户获取预先格式化为 KB、MB 或 GB 的大小。我认真思考了很长时间,因为这确实不是最好的设计模式。尽管如此,我并不是唯一一个喜欢将值格式化为更用户友好的形式的人。因此,让我向您展示一个我认为更好地遵循 PowerShell 脚本编写最佳实践的修订版本,同时还提供了数据格式化的灵活性。

扩展 PowerShell 对象

我欣赏 PowerShell 的优点之一是扩展或修改对象类型是多么容易。这是因为 PowerShell 具有可扩展类型系统。使用 Update-TypeData cmdlet,可以非常轻松地向对象类型添加新属性。这就是我决定采取的方法。我决定让“基本”对象保持非常简单,并以字节为单位显示目录大小。这意味着我删除了 -As 参数周围的所有代码。

#get the total size of all files in the .git folder
$stat = Get-Childitem -path $git -Recurse -File | Measure-Object -Property length -sum

#create the output
$obj = [PSCustomObject]@{
    Path  = $full
    Files = $stat.count
    Size  = $stat.sum
} #customobject

为了扩展类型,您需要知道类型名称。当像我在这里一样创建 PSCustomobject 时,这将需要一些额外的步骤来为自定义对象定义额外的类型名。这通常是通过如下代码完成的:

#insert a new typename
$obj.psobject.typenames.insert(0, "gitSize")
#write object to the pipeline
$obj

更新

感谢 Chris Warwick 的评论,有一种更好的方法来插入 PowerShell 中某个时候引入的类型名称,但我错过了。在对象本身中定义一个名为 PSTypeName 的属性。

$obj = [PSCustomObject]@{
    PSTypeName = "gitSize"
    Path       = $full
    Files      = $stat.count
    Size       = $stat.sum
} #customobject

它不会显示在对象的输出中,但将用于类型名。您可以通过将对象传递给 Get-Member 来验证它。

我还可以创建一个 PowerShell 类,该类从一开始就包含在类型名中。但这比我要进入的内容要复杂一些。现在来说说有趣的事情。

利用更新类型数据

我的函数现在将一个类型名为 gitSize 的对象写入管道。我决定我可能想看到的所有其他属性都是完全可选的。为了实现此目的,我将在函数外部使用 Update-TypeData 命令。由于无论如何我都需要使用该函数对脚本文件进行点源,因此我在函数定义之后添加了这些行。

Update-TypeData -TypeName gitSize -MemberType ScriptProperty -MemberName SizeKB -Value {$this.size / 1kb} -force
Update-TypeData -TypeName gitSize -MemberType ScriptProperty -MemberName SizeMB -Value {$this.size / 1mb} -force
Update-TypeData -TypeName gitSize -MemberType ScriptProperty -MemberName SizeGB -Value {$this.size / 1gb} -force
Update-TypeData -TypeName gitSize -MemberType NoteProperty -MemberName Computername -Value $env:COMPUTERNAME -force
Update-TypeData -TypeName gitSize -MemberType ScriptProperty -MemberName Date -Value {Get-Date} -force
Update-TypeData -TypeName gitSize -MemberType ScriptProperty -MemberName Name -Value {Split-Path -path $this.path -leaf} -force

我还添加了一些我一直在考虑的其他属性,例如计算机名和日期。是的,我可以将其中许多定义为自定义对象的一部分,在这种情况下,我将使用如下代码:

$obj = [PSCustomObject]@{
    Path  = $full
    Files = $stat.count
    Size  = $stat.sum
    SizeKB = $stat.sum/1kb
    Computername = $env:computername
} #customobject

无论如何,我知道默认情况下我只想查看路径、文件数量和大小(以字节为单位)。按照目前的情况,当我运行我的函数时,我将得到一个显示所有内容的对象。解决方案是使用 Update-TypeData 并定义一组默认属性。

#set default properties
Update-TypeData -TypeName gitSize -DefaultDisplayPropertySet "Path", "Files", "Size" -Force

当我运行该函数时,它将向管道写入 gitSize 对象,我将获得默认值。

[玩转系统] PowerShell 脚本 • 使用重新设计的 PowerShell 获取 Git 大小

但如果我想要的话,所有的属性都在那里。

[玩转系统] PowerShell 脚本 • 使用重新设计的 PowerShell 获取 Git 大小

扩展功能

我把原来的函数留在了 Github 上。这个版本可以在这里找到。

Get-GitSize2.ps1:

Function Get-GitSize {
  Get-GitSize

Path                     Files  Size
----                     -----  ----
C:\scripts\PiedPiperBox\    30 18456

Get the size of the .git folder from the current path. The size is in bytes.

.EXAMPLE
PS C:\> get-gitsize C:\scripts\DevOps-Courses\ | Select Path,Files,SizeMB

Path                       Files           SizeMB
----                       -----           ------
C:\scripts\DevOps-Courses\    29 50.8291053771973

Get the size of the git folder under C:\Scripts\Devops-Courses selecting a different set of properties.
.EXAMPLE
PS C:\> dir c:\scripts -Directory | Get-GitSize | Sort Size -descending | Select -first 5 -property Path,Files,SizeMB

Path                      Files           SizeMB
----                      -----           ------
C:\scripts\PS-AutoLab-Env    46 183.732244491577
C:\scripts\DevOps-Courses    29 50.8291053771973
C:\scripts\PSGUI             32 6.39523887634277
C:\scripts\Lab              132 1.67190265655518
C:\scripts\tips             530 1.66895771026611

Get the directories under C:\Scripts that have a .git folder and sort on the Size property in descending order. Then select the first 5 directories and use the specified properties.
.INPUTS
[System.String]
.NOTES
Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/

This is a variation of code posted at https://gist.github.com/jdhitsolutions/cbdc7118f24ba551a0bb325664415649
.LINK
Get-ChildItem
.LINK
Measure-Object
#>

    [cmdletbinding()]
    [Outputtype("gitSize")]
    Param (
        [Parameter(Position = 0, ValueFromPipeline, ValueFromPipelinebyPropertyName)]
        [alias("pspath")]
        [ValidateScript( {Test-Path $_})]
        [string]$Path = "."
    )

    Begin {
        Write-Verbose "[$((Get-Date).TimeofDay) BEGIN] Starting $($myinvocation.mycommand)"
    } #begin
    Process {
        $full = Convert-Path -Path $Path
        Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Processing path $full"
        $git = Join-Path -Path $full -childpath ".git"
        Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Testing $git"
        if (Test-Path -path $git) {

            Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Measuring $git"
            #get the total size of all files in the .git folder
            $stat = Get-Childitem -path $git -Recurse -File | Measure-Object -Property length -sum

  #create the output
            
            $obj = [PSCustomObject]@{
                PSTypeName = "gitSize"
                Path       = $full
                Files      = $stat.count
                Size       = $stat.sum
            } #customobject

            
            $obj
        } #if test-path
        else {
            Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Did not find $git"
        }
    } #process
    End {
        Write-Verbose "[$((Get-Date).TimeofDay) END    ] Ending $($myinvocation.mycommand)"
    } #end
}

#add custom properties
#these properties could also be added to the original object
Update-TypeData -TypeName gitSize -MemberType ScriptProperty -MemberName SizeKB -Value {$this.size / 1kb} -force
Update-TypeData -TypeName gitSize -MemberType ScriptProperty -MemberName SizeMB -Value {$this.size / 1mb} -force
Update-TypeData -TypeName gitSize -MemberType ScriptProperty -MemberName SizeGB -Value {$this.size / 1gb} -force
Update-TypeData -TypeName gitSize -MemberType NoteProperty -MemberName Computername -Value $env:COMPUTERNAME -force
Update-TypeData -TypeName gitSize -MemberType ScriptProperty -MemberName Date -Value {Get-Date} -force
Update-TypeData -TypeName gitSize -MemberType ScriptProperty -MemberName Name -Value {Split-Path -path $this.path -leaf} -force

#set default properties
Update-TypeData -TypeName gitSize -DefaultDisplayPropertySet "Path", "Files", "Size" -Force

和以前一样,您需要在本地保存文件并将其点源到 PowerShell 会话中。现在,我有了一些灵活性。我可以获取前面所示的默认输出,也可以运行这样的代码来利用附加属性。

[玩转系统] PowerShell 脚本 • 使用重新设计的 PowerShell 获取 Git 大小

我考虑过但没有采用的另一种方法是使用 format.ps1xml 文件。这也需要我定义一个类型名。使用这种方法,我必须创建一个特殊格式的 xml 文件来定义表或列表(通常这两个)视图。视图可以包含用于动态显示格式化为 KB 或 MB 的数据的代码。这是您在运行 Get-Process 时看到的进程对象完成的事情类型。当您单独运行 Get-Process 时,PowerShell 使用已定义的表格视图来处理格式化值的流程对象。但它不会改变底层对象。创建 xml 文件可能有点乏味,我今天不想陷入这个兔子洞。当然,在某些情况下您可能想同时利用类型和格式扩展,希望我们可以在以后的文章中重新讨论这个主题。

PowerShell 脚本编写是一个过程

同时,看一下代码。考虑一下我经历的设计过程。我写这些文章不仅是为了向您展示成品,也是为了向您传授概念和技术。不过,如果您发现它有帮助,那就是奖励。拥抱并享受。

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯