「[[マイクロソフト系技術情報 Wiki>http://techinfoofmicrosofttech.osscons.jp/]]」は、「[[Open棟梁Project>https://github.com/OpenTouryoProject/]]」,「[[OSSコンソーシアム .NET開発基盤部会>https://www.osscons.jp/dotNetDevelopmentInfrastructure/]]」によって運営されています。

-[[戻る>PowerShell]]

* 目次 [#a65a66fe]
#contents

* 概要 [#c192162a]
以前から、オブジェクトベースのプログラム、スクリプト(perl、[[WSH>VBS]])などは存在したが、~
PowerShellが唯一のオブジェクト・ベースのシェル(perlに似ている)である。~
# OSレイヤから少々遠いため[[シェル]]というより[[シェルスクリプト>スクリプティング]]という意見もある。

*詳細 [#gf337538]
**テキストベースからオブジェクトベースへ。 [#z99a6bd1]
皆、
-テキストベースの[[シェル]]と
-オブジェクトベースの[[シェル]]の

違いに混乱する。

-パイプラインで渡せる型はある。

-パイプラインで何が渡るかはGet-Memberコマンドレット調べる~
http://mojibake.seesaa.net/article/53585441.html

--[[シェル]]だが、プログラム、スクリプト(perl)のような仕様。

--変数、配列、Property、Method(.NETライク)、また、~
無名関数、delegate、検索条件をラムダ式的に・・・なども可能。~
 Like This
 
  ↓パイプ    ↓ラムダ式的な
  get-service | where-object {$_.Status -eq "Running"} 
 
  パイプしなくてもキャスト(暗黙)でつなげられる。
  
**オブジェクトのパイプラインとは? [#cac4db70]
-Unix/Linuxのshellコマンドや、Windowsのコマンドプロンプトでも、~
「|」を使って、コマンドを複数並べてパイプラインが記述できる。

-内部的には、標準出力のテキストを次のコマンドの標準入力へ渡している。

-PowerShellでは、PowerShellのオブジェクトをパイプラインで渡すことができる。
--そして、ほとんどのPowerShellコマンドがオブジェクトを出力する。
--また、オブジェクトには、多くのプロパティを含んでいる。
--後処理のために、オブジェクトにプロパティを追加できる。
--プロパティを判定してフィルタしたり、プロパティを使ってソートできる。
--最後に Format-List や Format-Table などのコマンドを使って、一部のプロパティを整形して表示できる。

-.ps1スクリプト内で定義する関数(function)や、自作のCmdletでも、~
オブジェクトを返すようにしておくと、再利用しやすくなります。

-パイプラインの例は、~
後述の [[オブジェクトへメンバー追加>#pbe1b175]]  の例を参照ください。

-パイプラインの詳細は、~
PowerShellコマンドプロンプトで「get-help about_pipeline」を参照ください。

**オブジェクトへメンバー追加する。 [#pbe1b175]
-PowerShellでは、Add-Member を使って、オブジェクトに動的にメンバーを追加できます。

-OSや他のライブラリが返したオブジェクトに、情報を追加しながら、~
パイプラインを使って、順次処理する。といったことができます。~

***スクリプト [#l3010bb9]

 function dirinfo {
   param(
    [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
    [object]$dir,
 
    [boolean]$totalup = $false 
   )
 
   # 空っぽの配列
   $dirs = @()
 
   # $dir へ プロパティ追加
   $dir | Add-Member -MemberType NoteProperty -Name TotalFiles -Value 0
   $dir | Add-Member -MemberType NoteProperty -Name TotalSize -Value 0
 
   foreach ($f in (get-childitem $dir.FullName)) {
     if ( $f.Attributes -band [System.IO.FileAttributes]::Directory ) {
       # サブフォルダの情報
       $ret = dirinfo $f $totalup
       if ( $totalup ) {
         # 末尾の情報を $dir へ加算
         $dir.TotalFiles += $ret[-1].TotalFiles
         $dir.TotalSize += $ret[-1].TotalSize
       }
       $dirs += $ret   # サブフォルダ全体を覚える
     } else {
       $dir.TotalFiles += 1
       $dir.TotalSize += $f.Length
       $dirs += $f
     }
   }
   $dirs += $dir   # $dir自身を末尾に覚える
 
   # 覚えたものをまとめて返す
   write-output $dirs
 }

***実行例 [#k8ba911b]
-実行例のパイプライン
   dirinfo (get-item "c:\program files") | sort-object totalsize -Descending | 
       where { $_.TotalSize -gt 1 } | select-object -first 5 | 
       format-list -Property TotalFiles, TotalSize, Fullname
   (行は折り返して表示しています。実行する際は、1行に入力してください。)

-ココでは、以下のことをしています
>
+get-item で C:\Program Files フォルダのオブジェクトを取得して、~
+dirinfo でサブフォルダのサイズを集計、~
+sort-obejct で TotalSize の大きい順に並び替えて、~
+where で TotalSize が 1以上のオブジェクトだけ抽出して、~
+select-object で 最初の 5 個だけ取り出し、~
+format-list で 特定のプロパティのみ表示。

*参考 [#e644e1b9]
-PowerShell:Windowsでおそらく最高のシェル~
http://programming-aip.blogspot.jp/2013/01/powershellwindows.html

--最近は、コマンドレットも充実してきて人気も出てきていると思います。

--分析中で面白いのは、~
「大量の出力を扱う場合は、オブジェクト・ベースが仇となる場合もある」~
という所である。

---理由は、大量テキスト処理可能なCUIのEXEにパイプさせれば上手く編集できるため。
---しかし、そもそも、Windowsの場合、強力なテキスト処理を実装するCUIのEXEが充実していない。

-Windows PowerShell: オブジェクトをカスタマイズするさまざまな方法~
http://technet.microsoft.com/ja-jp/magazine/hh750381.aspx~

-コンピューターで多くの領域を占有しているフォルダーを確認する方法はありますか~
http://gallery.technet.microsoft.com/scriptcenter/4e83afe2-ebdf-414a-bfc9-36e76b7e9750

----
Tags: [[:シェル]], [[:インフラストラクチャ]], [[:Windows]]

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS