PowerShell でディレクトリ以下のファイルを処理する場合、Get-ChildItem を使うのですが、Get-ChildItem で取得できるオブジェクトは、ファイルだけではなくディレクトリも一緒に取得されます。
ディレクトリかファイル化を見分ける際に、Attributes プロパティを見るのですが、ついうっかり「-eq "Directory"」みたいにな比較条件を書きたくなりますが、これは誤動作の元です。
なぜなら、Attributes プロパティは列挙型で複数の属性を持つ事が出来るため、「Directory」とかの文字列との比較はキャストがたまたまうまくいっただけで、実際には意図しない動作をするケースが多いのです。
FileAttributes Enum (System.IO) | Microsoft Docs
https://docs.microsoft.com/ja-jp/dotnet/api/system.io.fileattributes?WT.mc_id=WD-MVP-36880
Attributes はビットフラグなので、正しくディレクトリか否かを判別するにはビット演算をする必要があります。
ビットフラグから特定のビット状態を得るには、AND を取ります。
ディレクトリのフラグビットは、[System.IO.FileAttributes]::Directory なので、PowerShell のビット AND の -band を取ります。
単純なビット演算であれば、AND を取った後の値が 0 か否かで判断できますが、Attributes は
FileAttributes の型を持っているので、-band を取った結果も FileAttributes になってしまうため、単純に -ne 0
で判断すのは気持ちが悪いです。
(これもキャストがうまく効いてはくれますが...)
Uint32 とかにキャスティングしても良いのですが、そもそも Attributes のビット数が明記されていないし、将来的に型が変わった場合を想定すると安易に Uint にキャスティングするのも bug の原因になりそうな不安が残ります。
このため、ちょっとダサいのですが、AND した結果に想定ビットがセットされているかの比較をします、
(オブジェクト.Attributes -band [System.IO.FileAttributes]::Directory) -eq [System.IO.FileAttributes]::Directory
これで、ディレクトリかファイルかの区別が出来ますね。
他の属性も同様に確認することが出来ます。
Copyright © MURA All rights reserved.