我有从各种Linux服务器写入中央Windows NAS服务器的日志。它们以E:\ log格式:
E:\日志\过程1 \ log20140901.txt,
E:\日志\过程2 \ 20140901.txt,
E:\ LOG \ process3 \登录过程20140901.txt,
等
同时每周复制多个文件,因此创建日期不是确定最新文件的好方法。因此我编写了一个powershell函数来解析日期,我正在尝试迭代并获取每个文件夹中的最新文件,使用我的函数输出作为“日期”。我肯定做错了什么。
这是我到目前为止写的Powershell:
Function ReturnDate ($file)
{
$f = $file
$f = [RegEx]::Matches($f,"(\d{8})") | Select-Object -ExpandProperty Value
$sqlDate = $f.Substring(0,4) + "-" + $f.substring(4,2) + "-" + $f.substring(6,2)
return $sqlDate
}
Get-ChildItem E:\log\* |
Where {$_.PsIsContainer} |
foreach-object { Get-ChildItem $_ -Recurse |
Where {!$_.PsIsContainer} |
ForEach-Object { ReturnDate $_}|
Sort-Object ReturnDate -Descending |
Select-Object -First 1 | Select Name,ReturnDate
}
我似乎混淆了属性并导致“你无法在空值表达式错误上调用方法”,但我不确定该怎么做。
答案 0 :(得分:2)
我怀疑你的$f
变量为null,并且你试图在空值上调用一个方法(Substring)。试试这个:
Get-ChildItem E:\Log -File -Recurse | Where Name -Match '(\d{8})\.' |
Foreach {Add-Member -Inp $_ NoteProperty ReturnDate ($matches[1]) -PassThru} |
Group DirectoryName |
Foreach {$_.Group | Sort ReturnDate -Desc | Select -First 1}
这需要V3或更高版本。如果你在V1或V2上改为:
Get-ChildItem E:\Log -Recurse |
Where {!$_.PSIsContainer -and $_.Name -Match '(\d{8})\.'} |
Foreach {Add-Member -Inp $_ NoteProperty ReturnDate ($matches[1]) -PassThru} |
Group DirectoryName |
Foreach {$_.Group | Sort ReturnDate -Desc | Select -First 1}
答案 1 :(得分:1)
当我尝试它时,你的代码对我来说没问题,直到你做了select
你要求的名字并且当这些属性不存在时返回。使用这些值创建自定义对象将使您的代码工作。我也从你的管道中删除了一些逻辑。最终结果应该仍然有用(我只是制作了一些虚拟文件来测试,就像你的例子一样)。
使用原始代码,您可以拥有类似的内容。这只适用于v3或更高版本。如果需要,简单的更改可以使其工作更低。大多数情况下[pscustomobject]
。
Function ReturnDate ($file)
{
$f = $file
$f = [RegEx]::Matches($f,"(\d{8})") | Select-Object -ExpandProperty Value
$sqlDate = $f.Substring(0,4) + "-" + $f.substring(4,2) + "-" + $f.substring(6,2)
[pscustomobject] @{
'Name' = $file.FullName
'ReturnDate' = $sqlDate
}
}
Get-ChildItem C:\temp\E\* -Recurse |
Where-Object {!$_PSIsContainer} |
ForEach-Object{ReturnDate $_} |
Sort-Object ReturnDate -Descending |
Select-Object -First 1
答案 2 :(得分:1)
Sort-Object
cmdlet支持按自定义脚本块排序,并按脚本块返回的任何内容进行排序。因此,使用正则表达式来获取时间戳并将其返回。
Get-ChildItem E:\log\* -Directory |
ForEach-Object {
Get-ChildItem $_ -Recurse -File |
Sort-Object -Property {
if( $_.Name -match '(\d{8})' )
{
return $Matches[1]
}
Write-Error ('File ''{0}'' doesn't contain a timestamp in its name.' -f $_.FullName)
} |
Select-Object -Last 1 |
Select Name,ReturnDate
}
请注意,Select-Object -First 1
已更改为Select-Object -Last 1
,因为日期将从最旧到最新排序。