在powershell中处理哈希表

发布于 2025-01-14 15:05:21 字数 1860 浏览 0 评论 0原文

我想要一个 Powershell 脚本来告诉我特定目录中文件的每个版本的最新版本。文件名由基本名和时间戳构成,

例如StaffTS2016_20220308010543.7z

StaffTS2016 是我感兴趣的基本名称。由于我引用了文件系统中的 LastAccessTime,因此可以丢弃时间戳。我想知道 StaffTS2016 的最新版本:可以多次出现具有此基本名称的文件。我想知道目录中每个基本名称的最新年龄。这篇文章已经让我完成了

使用以下命令获取文件的年龄powershell

$strDays = @{l="Days";e={((Get-Date) - $_.LastAccessTime).Days}}
$path = "D:\HVBackup\VP20"
$output1 = Get-ChildItem $path -File | Select-Object Name, $strDays | Out-String
名称
StaffTS2016_20220308010543.7z8
StaffTS2016_20220314231747.7z1
vc2012R2DC1_20220308022625.7z4
vc2012R2DC1_20220314230635.7z2
vcApache_20220308023655.7z5
vcApache_20220314235915.7z1
vcEX1a2012_20220307230943.7z8
vcSQL2016_20220308014925.7z8
vcSQL2016_20220314223040.7z1

我无法弄清楚如何直接通过扩展管道或通过后处理来处理生成的哈希表,以获取我想要的信息。

如您所见,我的哈希表有两个字段:Name 和 Days。我想从 $.Name 中提取 BaseName 作为 $.Name.split('_')[0]。然后,如果输出表中不存在 BaseName,我想将 (BaseName, Days) 添加到输出表中,如果存在并且新的 Days 较低,则将 Days 更新为较低的值。我可以用其他语言执行此操作,但不能使用 Powershell。

所需的输出是

NameDays
StaffTS20161
vc2012R2DC12
vcApache1
vcEX1a20128
vcSQL20161

,这会告诉我备份 vcEX1a2012 时出现问题

I want a Powershell script to tell me the youngest of each version of a file in a particular directory. Filenames are constructed from a basename and a timestamp

e.g. StaffTS2016_20220308010543.7z

StaffTS2016 is the basename I am interested in. The timestamp can be discarded since I refer to the LastAccessTime in the filesystem. I want to know the youngest version of StaffTS2016: there can be multiple occurences of files with this basename. I want to know the age of the newest, for each basename in the directory. This SO article has got me part way there

Get the age of a file using powershell

$strDays = @{l="Days";e={((Get-Date) - $_.LastAccessTime).Days}}
$path = "D:\HVBackup\VP20"
$output1 = Get-ChildItem $path -File | Select-Object Name, $strDays | Out-String
NameDays
StaffTS2016_20220308010543.7z8
StaffTS2016_20220314231747.7z1
vc2012R2DC1_20220308022625.7z4
vc2012R2DC1_20220314230635.7z2
vcApache_20220308023655.7z5
vcApache_20220314235915.7z1
vcEX1a2012_20220307230943.7z8
vcSQL2016_20220308014925.7z8
vcSQL2016_20220314223040.7z1

I cannot figure out how to process the resulting hash table, either directly via extending the pipeline, or by post-processing, to derive the information I want.

As you can see, my hash table has two fields, Name and Days. From $.Name I want to extract BaseName as $.Name.split('_')[0]. Then I want to add (BaseName, Days) to my output table if BaseName does not exist in the output table, and update Days to the lower value if it does exist and the new Days is lower. I could do this in other languages but not Powershell.

The desired output is

NameDays
StaffTS20161
vc2012R2DC12
vcApache1
vcEX1a20128
vcSQL20161

and this would tell me at a glance that there has been a problem with backing up vcEX1a2012

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

旧伤慢歌 2025-01-21 15:05:21

顾名思义,Out-String 将输出 Get-ChildItem ... | Select ...字符串不是哈希表)中,这无疑使数据处理起来很麻烦。

相反,首先根据名称的第一部分将文件分组在一起,然后根据时间戳对每组中的文件进行排序:

# prepare calculated property selectors for both the name and the days for later
$selectors = @(
  @{Label="Days"; Expression = {((Get-Date) - $_.LastAccessTime).Days}}
  @{Label="Name"; Expression = { $_.BaseName.Split('_')[0] }}
)

# discover the files
$path = "D:\HVBackup\VP20"
$files = Get-ChildItem $path -File

# group the files by the first part of their base name
$files |Group-Object { $_.BaseName.Split('_')[0] } |ForEach-Object {
  # then pick only the newest from each, based on the timestamp part of the name
  $_.Group |Sort-Object { $_.BaseName.Split('_')[-1] } -Descending |Select-Object -First 1 -Property $selectors
}

As the name implies, Out-String turns the output from Get-ChildItem ... | Select ... into a string (not a hashtable), which undoubtedly makes the data cumbersome to work with.

Instead, start by grouping the files together based on the first part of the name, then sort the files in each group according to the timestamp:

# prepare calculated property selectors for both the name and the days for later
$selectors = @(
  @{Label="Days"; Expression = {((Get-Date) - $_.LastAccessTime).Days}}
  @{Label="Name"; Expression = { $_.BaseName.Split('_')[0] }}
)

# discover the files
$path = "D:\HVBackup\VP20"
$files = Get-ChildItem $path -File

# group the files by the first part of their base name
$files |Group-Object { $_.BaseName.Split('_')[0] } |ForEach-Object {
  # then pick only the newest from each, based on the timestamp part of the name
  $_.Group |Sort-Object { $_.BaseName.Split('_')[-1] } -Descending |Select-Object -First 1 -Property $selectors
}
泪眸﹌ 2025-01-21 15:05:21

您可以将最后一个命令更改为类似这样的

$output1 = Get-ChildItem $path -File | Select-Object Name, $strDays |
  ForEach-Object { $_.Name = $_.Name.split('_')[0]; $_ } | 
  Group-Object -Property Name | 
  ForEach-Object { $_.Group | Sort-Object -Property Days | Select-Object -First 1 }

Group-Object ,您可以将每个文件与具有相同名称的文件进行比较,这些文件是在前面的 ForEach-Object 中设置的$_.Name.split('_')[0] 就像您指定的那样。

You could change the last command to something like this

$output1 = Get-ChildItem $path -File | Select-Object Name, $strDays |
  ForEach-Object { $_.Name = $_.Name.split('_')[0]; $_ } | 
  Group-Object -Property Name | 
  ForEach-Object { $_.Group | Sort-Object -Property Days | Select-Object -First 1 }

Group-Object lets you compare each file to the ones with the same name, which are set in the preceding ForEach-Object with $_.Name.split('_')[0] like you specified.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文