マイクロソフト系技術情報 Wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。

目次

概要

以前から、オブジェクトベースのプログラム、スクリプト(perl、WSH)などは存在したが、
PowerShellが唯一のオブジェクト・ベースのシェル(perlに似ている)である。

# OSレイヤから少々遠いためシェルというよりシェルスクリプトという意見もある。

詳細

テキストベースからオブジェクトベースへ。

皆、

違いに混乱する。

  • パイプで渡せる型はある。
  • シェルだが、プログラム、スクリプト(perl)のような仕様。
  • 変数、配列、Property、Method(.NETライク)、また、
    無名関数、delegate、検索条件をラムダ式的に・・・なども可能。
    Like This
    
     ↓パイプ    ↓ラムダ式的な
     get-service | where-object {$_.Status -eq "Running"} 
    
     パイプしなくてもキャスト(暗黙)でつなげられる。
     

オブジェクトのパイプラインとは?

  • Unix/Linuxのshellコマンドや、Windowsのコマンドプロンプトでも、
    「|」を使って、コマンドを複数並べてパイプラインが記述できます。
  • ですが、それらは、標準出力のテキストを次のコマンドの標準入力へ渡す、にすぎません。
  • PowerShellでは、PowerShellのオブジェクトをパイプで渡すことができます。
    • そして、ほとんどのPowerShellコマンドがオブジェクトを出力します。
    • また、オブジェクトには、多くのプロパティを含んでいます。
    • 後処理のために、オブジェクトにプロパティを追加することもできます。
    • このため、プロパティを判定してフィルタしたり、プロパティを使ってソートできます。
    • 最後に Format-List や Format-Table などのコマンドを使って、一部のプロパティを整形して表示します。
  • .ps1スクリプト内で定義する関数(function)や、自作のCmdletでも、
    オブジェクトを返すようにしておくと、再利用しやすくなります。
  • パイプラインの詳細は、
    PowerShellコマンドプロンプトで「get-help about_pipeline」を参照ください。

オブジェクトへメンバー追加する。

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

スクリプト

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
}

実行例

  • 実行例のパイプライン
      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行に入力してください。)
  • ココでは、以下のことをしています
    1. get-item で C:\Program Files フォルダのオブジェクトを取得して、
    2. dirinfo でサブフォルダのサイズを集計、
    3. sort-obejct で TotalSize? の大きい順に並び替えて、
    4. where で TotalSize? が 1以上のオブジェクトだけ抽出して、
    5. select-object で 最初の 5 個だけ取り出し、
    6. format-list で 特定のプロパティのみ表示。

参考

  • 最近は、コマンドレットも充実してきて人気も出てきていると思います。
  • 分析中で面白いのは、
    「大量の出力を扱う場合は、オブジェクト・ベースが仇となる場合もある」
    という所である。
  • 理由は、大量テキスト処理可能なCUIのEXEにパイプさせれば上手く編集できるため。
  • しかし、そもそも、Windowsの場合、強力なテキスト処理を実装するCUIのEXEが充実していない。

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


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-02-13 (火) 16:47:51 (98d)