Ste*_*eve 4 powershell file-io filenames special-characters
我想从构建服务器中清除日志文件,保留最近几天。我的进程创建的日志文件没有问题。这工作正常:
$logFolders = Get-ChildItem $buildBase -Recurse -include logs -Attributes D
$logFolders | ForEach-Object { Get-ChildItem $_.fullname -filter *.log | where >{$_.lastwritetime -lt (get-date).adddays(-$purgeAfter) -and -not $_.psiscontainer} |% {remove-item $_.fullname -force} };
Run Code Online (Sandbox Code Playgroud)
但是,构建工具生成的日志如下所示:
lrFR_WebHelp - Friday, February 28, 2014 [9.00 PM].mclog
Run Code Online (Sandbox Code Playgroud)
Get-ChildItem $frReports\Reports -filter *.mclog | where {$_.lastwritetime -lt (get-date).adddays(-$purgeAfter) -and -not $_.psiscontainer}| % {write-host ("'" + $frReports + '\Reports' + '\' + $_ + "'") }
Run Code Online (Sandbox Code Playgroud)
输出:
'D:\scratch\Reports\lrFR_WebHelp - Friday, February 28, 2014 [9.00 PM].mclog'
Run Code Online (Sandbox Code Playgroud)
但试图删除:
Get-ChildItem $frReports\Reports -filter *.mclog | where {$_.lastwritetime -lt (get-date).adddays(-$purgeAfter) -and -not $_.psiscontainer}| % {remove-item ("'" + $frReports + '\Reports' + '\' + $_ + "'") }
Run Code Online (Sandbox Code Playgroud)
输出:
remove-item : Cannot find drive. A drive with the name ''D' does not exist.
At line:1 char:145
+ ... container}| % {remove-item ("'" + $frReports + '\Reports' + '\' + $_ + "'") }
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: ('D:String) [Remove-Item], DriveNotFoundException
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand
Run Code Online (Sandbox Code Playgroud)
更改为 unix 斜杠 ('/') 或转义斜杠 ('\\') 不会改变结果
这个:
$filesToDelete = Get-ChildItem $frReports\Reports -filter *.mclog | where {$_.lastwritetime -lt (get-date).adddays(-$purgeAfter) -and -not $_.psiscontainer}
Push-Location -path D:\scratch\Reports
$filesToDelete | ForEach-Object {
$fname = ("'" + $_ + "'");
write-host $fname;
remove-item $fname -Force;
remove-item $_;
}
Run Code Online (Sandbox Code Playgroud)
输出这个:
'lrFR_WebHelp - Friday, February 28, 2014 [9.00 PM].mclog'
'lrFR_WebHelp - Friday, March 14, 2014 [10.24 PM].mclog'
Run Code Online (Sandbox Code Playgroud)
但不会删除文件。
$fso = New-Object -ComObject Scripting.FileSystemObject
$buildBase = "D:\scratch";
$logFolders = Get-ChildItem $buildBase -Recurse -include Reports -Attributes D
$logFolders | ForEach-Object { Get-ChildItem $fso.GetFile($_.FullName).ShortPath -filter *.MCL | where {$_.lastwritetime -lt (get-date).adddays(-$purgeAfter) -and -not $_.psiscontainer}} #|% {write-host $_.fullname} };
Run Code Online (Sandbox Code Playgroud)
输出:
Exception calling "GetFile" with "1" argument(s): "Exception from HRESULT: 0x800A0035 (CTL_E_FILENOTFOUND)"
At line:1 char:32
+ $logFolders | ForEach-Object { Get-ChildItem $fso.GetFile($_.FullName).ShortPath ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
Run Code Online (Sandbox Code Playgroud)
没有任何运气在 PowerShell 中获得有关 $fso.GetFile 的更多信息。谷歌这次让我失望了。
任何人都可以帮忙吗?我更喜欢纯粹的 PowerShell 解决方案,但会感谢任何有效的解决方案。
您的问题是由文件名中的方括号引起的。当您将带有路径的字符串传递到 的(隐式)-Path参数时Remove-Item,方括号将被解释为通配符。[9.00 PM]因此,子字符串将匹配单个字符,即M、P、9、0、 点或空格。您可以使用-LiteralPath而不是-Path通过更改以下内容来避免这种行为:
... | % { Remove-Item $_.FullName -Force }
Run Code Online (Sandbox Code Playgroud)
进入这个:
... | % { Remove-Item -LiteralPath $_.FullName -Force }Run Code Online (Sandbox Code Playgroud)
但是,Remove-Item接受管道输入,因此您可以完全删除循环并直接从管道读取项目:
... | Remove-Item -Force
Run Code Online (Sandbox Code Playgroud)
这种方式Remove-Item从整个FileInfo对象中获取Get-ChildItem并自动执行 The Right Thing™。
附带说明:您可以通过删除循环来进一步简化代码,因为不仅Remove-Item从管道中读取,而且Get-ChildItem还从管道中读取。像这样的事情应该可以正常工作:
$limit = (Get-Date).AddDays(-$purgeAfter)
Get-ChildItem $buildBase -Recurse -Include logs -Attributes D |
Get-ChildItem -Filter *.mclog |
Where-Object { $_.LastWriteTime -lt $limit -and -not $_.PSIsContainer } |
Remove-Item -Force
Run Code Online (Sandbox Code Playgroud)