簡體   English   中英

PowerShell 刪除項目成功但拋出異常

[英]PowerShell remove-item succeeds but throws exception

我在 Mercurial 存儲庫的根目錄中運行以下命令。 我想刪除以“.hg”開頭的所有文件和文件夾:

gci -rec -filter ".hg*" | remove-item -recurse -force

奇怪的是,它確實有效,但仍然產生以下異常:

Get-ChildItem : Could not find a part of the path 'C:\temp\WSCopyTest\MyCompany.Services.DaftPunk\.hg\'.
At line:1 char:4
+ gci <<<<  -rec -filter ".hg*" | remove-item -recurse -force
    + CategoryInfo          : ReadError: (C:\temp\WSCopyT...es.DaftPunk\.hg:String) [Get-ChildItem], DirectoryNotFoundException
    + FullyQualifiedErrorId : DirIOError,Microsoft.PowerShell.Commands.GetChildItemCommand

因為異常是由Get-ChildItem引發的,我懷疑我對 PowerShell 中的流水線的理解是有缺陷的。 就像Get-ChildItem找到一個項目,將其傳遞給管道中的下一個 cmdlet,然后查找下一個? 它是這樣工作的嗎?

以下應該是一個可以復制問題的腳本,但是,在同一台機器上,它可以完美地工作:

$repoRoot = "C:\Temp\HgDeleteTest\MyRepo"
remove-item $repoRoot -recurse -force
md $repoRoot
pushd $repoRoot
hg.exe init
add-content ShouldBeLeftBehind.txt "This is some text in a file that should be left behind once the various .hg files/directories are removed."
add-content .hgignore syntax:glob
add-content .hgignore *.dll
add-content .hgignore *.exe
hg.exe commit --addremove --message "Building test repository with one commit."
gci -rec -filter ".hg*" | remove-item -recurse -force
popd

會不會是您要刪除一個以.hg 開頭的文件夾,而該文件夾又包含一個以.hg 開頭的文件,但該文件不再存在?

以下將其刪除僅限於文件,並排除文件夾。

gci -rec -filter ".hg*" | Where {$_.psIsContainer -eq $false} | remove-item -recurse -force

然后通過刪除文件夾再次運行它:

gci -rec -filter ".hg*" | Where {$_.psIsContainer -eq $true} | remove-item -recurse -force

我最終將搜索與刪除分開。 我相信我的問題與默認情況下管道的工作方式(即一次一個項目)有關,但我無法構建測試來檢查它。

無論如何,以下工作正常:

$hgObjects = gci -rec | ?{ $_.name -like ".hg*" -and $_.name -ne ".hgignore" }
remove-item $hgObjects -force -recurse

使用這種樣式, remove-item cmdlet 獲取找到的項目數組並通過它們工作。

我原始示例中的.hg文件夾中沒有任何名為.hg*的內容,所以我看不到發生了什么。 感覺更像是試圖兩次刪除文件夾,我覺得這很奇怪。 我想知道它是否實際上是此標准 .NET 行為的 PowerShell 表現形式:

只要集合保持不變,枚舉數就保持有效。 如果對集合進行了更改,例如添加、修改或刪除元素,則枚舉器可能會失效,並且對 MoveNext 或 Reset 的下一次調用可能會引發 InvalidOperationException。 如果集合在 MoveNext 和 Current 之間進行了修改,則 Current 返回它設置為的元素,即使枚舉器已經失效。 (取自http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.getenumerator(v=vs.71).aspx )。

我希望 Antony 是正確的 - 在 gci 上使用 -recurse 將枚舉匹配“.hg *”的文件和目錄。 該目錄將首先返回。 然后remove-item先刪除目錄,-force開關刪除里面的所有文件。 然后它會嘗試刪除該目錄中與“.hg*”匹配的文件(gci 運行時就在那里),但現在它們已經消失了。 這應該停止錯誤:

gci ".hg*" -recurse | select -expand fullname | sort length -desc | remove-item -force

按長度降序對全名進行排序可確保在刪除該目錄中所有匹配的文件之前,不會刪除匹配的父目錄。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM