2011-07-20 15 views
1

私はMercurialリポジトリのルートディレクトリに次のコマンドを実行しています。私は「の.hg」で始まるすべてのファイルとフォルダを削除する:PowerShell remove-itemは成功しましたが例外をスローします

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はアイテムを見つけてパイプラインの次のコマンドレットに渡し、次のコマンドレットを探します。それはどういう仕組みですか?

以下は、同じマシン上で、問題を再現するスクリプトをすることになっていたが、それは完璧に動作します:

$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 
+0

同じマシンで動作するのと同じ問題ですが、別のマシンでこのエラーが発生します。 – johntrepreneur

+0

2つの動作セットがある場合は、それがパワーシェルバージョンの問題である可能性があります。 – johntrepreneur

答えて

1

を私は除去から検索を分離することになりました。問題は配管がデフォルトで動作する(一度に1つのアイテム)ということでしたが、確認するためのテストを作成できませんでした。いずれの場合においても

、次は正常に動作します:

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

このスタイルを使用して、remove-itemコマンドレットは、見つかった項目の配列を取得し、それらを介して動作します。

オリジナルの例の.hgフォルダには.hg*という名前のものはありませんでしたので、何が起こっているのかわかりません。それは2回フォルダを削除しようとしているように感じました。私は非常に奇妙です。それは実際にこの標準の.NET行動のPowerShellの現れだ場合、私は疑問に思う:

列挙子が長いコレクションが 変わらとしてとして有効です。 要素を変更または削除するなど、コレクションに変更が加えられた場合、列挙子は無効になり、 MoveNextまたはResetへの次の呼び出しで InvalidOperationExceptionがスローされます。コレクションが MoveNextとCurrentの間で変更された場合、列挙子が既に無効化されていても、Currentはそれが設定されている要素 を返します。 (http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.getenumerator(v=vs.71).aspxから得た)。

+0

はい、私はちょうど同じ問題を遭遇し、同じ修正を使用しました。私はget-childitemをremove-itemから分割すると、アイテムの削除を始めるのにずっと時間がかかることに気付きました。これは、get-childitemが、最初の結果を次の操作(この場合はremove-item)に使用可能になると直ちにパイプし、完了後も続行することを示しています。 –

1

が、それはあなたがの.hgで始まるフォルダを削除していることだろう.hgで始まるファイルが含まれていますが、そのファイルは存在しません。

0

Antonyが正しいと思っています--GCiの-recurseを使用すると、 ".hg *"と一致するファイルとディレクトリの両方が列挙されます。ディレクトリが最初に返されます。次に、remove-itemはディレクトリを最初に削除し、-forceスイッチはその中のすべてのファイルを削除します。次に、そのディレクトリにあって ".hg *"と一致するファイル(gciが実行されたときにそこにあったファイル)を削除しようとしましたが、それらは今すぐ削除されています。これは、エラーを停止する必要があります。長さの降順でフルネームをソート

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

は、そのディレクトリ内のすべての一致するファイルが削除される前に、何もマッチした親ディレクトリが削除されていないことを保証します。

1

以下は、ファイルの削除のみを制限し、フォルダを除外します。

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

その後、フォルダを削除することによって、それを再度実行します。

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

なぜフォルダを削除しないのですか?私はMercurialが.hgフォルダの外でそのようなファイルを生成するとは思わない。 – JasonMArcher

関連する問題