删除带有特殊字符的文件

时间:2014-04-13 11:45:21

标签: powershell file-io special-characters filenames

我想从构建服务器清除日志文件,保留最近几天。我的进程创建的日志文件没有问题。这很好用:

$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} };

但是,构建工具生成的日志如下所示:

lrFR_WebHelp - Friday, February 28, 2014 [9.00 PM].mclog

我试过引用文件名:

Get-ChildItem $frReports\Reports -filter *.mclog | where {$_.lastwritetime -lt (get-date).adddays(-$purgeAfter) -and -not $_.psiscontainer}| % {write-host ("'" + $frReports + '\Reports'  + '\' + $_ + "'") }

输出:

'D:\scratch\Reports\lrFR_WebHelp - Friday, February 28, 2014 [9.00 PM].mclog'

但是试图删除:

Get-ChildItem $frReports\Reports -filter *.mclog | where {$_.lastwritetime -lt (get-date).adddays(-$purgeAfter) -and -not $_.psiscontainer}| % {remove-item ("'" + $frReports + '\Reports'  + '\' + $_ + "'") }

输出:

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

更改为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 $_;
}

输出:

'lrFR_WebHelp - Friday, February 28, 2014 [9.00 PM].mclog'
'lrFR_WebHelp - Friday, March 14, 2014 [10.24 PM].mclog'

但不删除文件。

最后,在互联网上寻找线索之后,我尝试了fso对象

   $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}  };

输出:

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

在PowerShell中获取有关$ fso.GetFile的更多信息没有任何运气。谷歌这次让我失望了。

有人可以帮忙吗?我更喜欢纯粹的PowerShell解决方案,但对任何有效的方法都会感激不尽。

1 个答案:

答案 0 :(得分:2)

您的问题是由文件名中的方括号引起的。当您将带有路径的字符串传递给Remove-Item的(隐式)-Path参数时,方括号将被解释为wildcard characters。因此,子字符串[9.00 PM]将匹配MP90,点或空格的单个字符。您可以使用-LiteralPath代替-Path来通过更改此内容来避免此行为:

... | % { Remove-Item $_.FullName -Force }

进入这个:

... | % { Remove-Item -LiteralPath $_.FullName -Force }

但是,Remove-Item接受管道输入,因此您可以完全放弃循环并直接从管道中读取项目:

... | Remove-Item -Force

这样Remove-ItemGet-ChildItem获取整个FileInfo对象并自动执行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