web-dev-qa-db-ja.com

PSCustomObjectではなく生のタイプ(例えばString)を返すSelect-Objectを取得する方法は?

次のコードはPSCustomObjectsの配列を提供しますが、どのようにしてそれを取得してStringsの配列を返すことができますか?

$files = Get-ChildItem $directory -Recurse | Select-Object FullName | Where-Object {!($_.psiscontainer)}

(二次的な質問として、psiscontainerの部分は何ですか?オンラインの例からコピーしました)

Post-Accept Edit: 2つのすばらしい答えです。両方に印を付けてください。元の答えを授与しました。

33
Mark Ingram

必要なプロパティをオブジェクトから選択するだけです。この場合、FullName

$files = Get-ChildItem $directory -Recurse | Select-Object FullName | Where-Object {!($_.psiscontainer)} | foreach {$_.FullName}

編集:「foreachは何をしているのですか?列挙するものは何ですか?」と尋ねるマークの説明

Sung Meisterの説明は非常に優れていますが、役立つかもしれないので、ここにウォークスルーを追加します。

重要な概念はパイプラインです。細いチューブを次々と転がる一連のピンポンボールを想像してください。これらは、パイプライン内のオブジェクトです。パイプラインの各ステージ(パイプ(|)文字で区切られたコードセグメント)には、パイプが入り、パイプが出ます。 1つのステージの出力は、次のステージの入力に接続されます。各ステージは、オブジェクトが到着するとそれらを受け取り、処理を行い、それらを出力パイプラインに送り返すか、新しい置換オブジェクトを送り出します。

Get-ChildItem $directory -Recurse

Get-ChildItemは、ファイルシステムを調べて、検出した各ファイルとディレクトリを表すFileSystemInfoオブジェクトを作成し、それらをパイプラインに配置します。

Select-Object FullName

Select-Objectは、到着した各FileSystemInfoオブジェクトを取得し、FullNameプロパティ(この場合はパス)を取得し、作成した新しいカスタムオブジェクトにそのプロパティを配置し、そのカスタムオブジェクトをパイプラインに配置します。

Where-Object {!($_.psiscontainer)}

これはフィルターです。各オブジェクトを取得して検査し、何らかの条件に応じて送信または破棄します。ところで、ここのコードにはバグがあります。ここに到着するカスタムオブジェクトには、psiscontainerプロパティがありません。この段階では実際には何もしません。 Sung Meisterのコードの方が優れています。

foreach {$_.FullName}

Foreach(長い名前はForEach-Object)は、到着した各オブジェクトを取得し、ここでは文字列であるFullNameプロパティを取得します。さて、ここに微妙な部分があります。消費されない、つまり、変数によってキャプチャされないか、何らかの方法で抑制されない値は、出力パイプラインに入れられます。実験として、このステージを次のように置き換えてみてください。

foreach {'hello'; $_.FullName; 1; 2; 3}

実際に試してみて、出力を調べてください。そのコードブロックには4つの値があります。それらのどれも消費されません。これらはすべて出力に表示されることに注意してください。今これを試してください:

foreach {'hello'; $_.FullName; $ x = 1; 2; 3}

値の1つが変数によってキャプチャされていることに注意してください。出力パイプラインには表示されません。

35
dan-gph

ファイル名の文字列を取得するには、使用できます

$files = Get-ChildItem $directory -Recurse | Where-Object {!($_.psiscontainer)} | Select-Object -ExpandProperty FullName

-ExpandPropertyパラメータを使用すると、指定したプロパティのタイプに基づいてオブジェクトを取得できます。

さらなるテストにより、これはV1では機能しなかったが、その機能はV2 CTP3で修正されたことが示されています。

22
Steven Murawski

V1の場合、プロファイルに次のフィルターを追加します。

filter Get-PropertyValue([string]$name) { $_.$name }

次に、これを行うことができます:

gci . -r | ?{!$_.psiscontainer} | Get-PropertyName fullname

ところで、 PowerShell Community Extensions を使用している場合、これはすでにあります。

V2でSelect-Object -Expandを使用する機能に関しては、これはかわいいトリックですが、明らかではなく、Select-Objectや-Expandが意図したものではありません。 -Expandは、LINQのSelectManyとSelect-Objectが複数のプロパティをカスタムオブジェクトに投影することと同じように、フラット化に関するものです。

4
Keith Hill