Windows PowerShell

続すてきなパイプラインの手法

Don Jones

 

先月は、複雑なタスクを 1 行の Windows PowerShell コードで実行できるようにする、パラメーターのバインドを活用するパイプラインの手法を紹介しました。

先月の内容を簡単に振り返っておきましょう。Active Directory ドメインに作成する必要がある新しいユーザーに関する情報を含むコンマ区切り値 (CSV) 形式のファイルを作成し、この CSV ファイルの列見出しが、New-ADUser コマンドレットのパラメーターと一致するようにしました (このコマンドレットは、Windows Server 2008 R2 に同梱されていますが、Windows Server 2003 ドメインでも使用できます)。列見出しには、Department、City、Name、GivenName、Surname などの値を設定しました。New-ADUser コマンドレットでは、プロパティ名でパイプライン入力をバインドするので、このような列見出しを使用すると、次の 2 つのコマンドレットを使用するだけで、ユーザーを作成できます。

Import-CSV c:\new-users.csv | New-ADUser

Import-CSV コマンドレットでは、CSV ファイルの各行のデータに対応するオブジェクトを出力し、出力されたオブジェクトには CSV ファイルの列名と対応するプロパティがあります。ここでは、CSV ファイルに、New-ADUser コマンドレッドのすべての必要なパラメーターが含まれていたので、パラメーターを手動で指定する必要はありませんでした。ですが、次のように、組織単位など、すべてのユーザーで有効とは限らないパラメーターを指定することは可能です。

Import-CSV c:\new-users.csv | New-ADUser –organization "OurCompany"

この例は、Windows PowerShell の威力を実によく表しています。VBScript では、このタスクを実行するのに複数行のスクリプトを使用する必要がありました (Windows PowerShell でも、同じように複数行のスクリプトを使用してタスクを実行することは可能です)。ですが、少し時間を取ってパイプラインのしくみを理解すると、いくつかの適切に記述されたコマンドレットを使用することで、このスクリプトは 2 つの単純なコマンドになります。

問題点

私の Web サイト (www.ConcentratedTech.com、英語) では、数名の洞察力のある読者の方から、先月のコラムで紹介した手法は CSV ファイルの列名が New-ADUser のパラメーター名と完全に一致する場合にしか機能しないという指摘を受けました。管理者が作成した CSV ファイルであれば、列名がパラメーター名と完全に一致していることを当てにできます。ですが、人事部の担当者が作成したものである場合、列名には First Name、Last Name などのような表記が使用されている可能性が高くなり、これでは New-ADUser コマンドレットで、プロパティをパラメーターに自動的にバインドできません。

人事部の担当者から渡されたファイルやデータベースを編集することは可能です。ですが、私たちがコンピューターを発明したのは、このような単調な作業から逃れるためではなかったのでしょうか。もちろん、Windows PowerShell には、プロパティの名前を簡単かつ迅速に変更できる機能が用意されています。それは、Select-Object コマンドレットです。

Select-Object コマンドレットでは、非常に多数の処理を実行できるので、使用方法を学習するのには時間がかかります。たとえば、主なタスクの 1 つは、その時点で必要ないプロパティを削除することによってオブジェクトを簡略化することです。このコマンドレットに対して必要なプロパティを指定するだけで、必要なプロパティのみを備えたオブジェクトが出力されます。この処理は、画面出力やテキスト ファイルの状態を見やすくするのに便利です。たとえば、次のように使用できます。

Get-WmiObject Win32_OperatingSystem | Select-Object BuildNumber,ServicePackMajorVersion

もう 1 つの用途は、次のように -first または -last パラメーターを使用して、パイプラインでオブジェクトのサブセットを選択することです。

Get-Process | Sort VM –desc | Select –first 10

ここでは、完全なコマンドレットの名前ではなく Select というエイリアスを使用していることに注意してください。

解決策

見落とされがち機能ですが、Select-Object コマンドレットでは、必要なプロパティを選択できるだけでなく、プロパティの名前を変更できます。このコマンドレットの詳細なヘルプ情報を読んだことがあれば、この機能についてはご存じで、その使い方の例もご覧になったことがあるでしょう (Help Select -full というコマンドを実行すると、Select-Object の詳細なヘルプ情報が表示されます。このコマンドは、すべてのコマンドレットについて実行してみることをお勧めします)。その例を次に示します。

Import-CSV c:\new-users.csv | Select @{Name="Surname";Expression={$_."Last Name"}}

CSV ファイルに Last Name という名前の列がある場合、この列名は Surname に変更されます。その結果、出力のプロパティは、New-ADUser コマンドレットのパラメーター名に一致します。ここでは、ハッシュテーブル (別称、"ディクショナリ" または "連想配列") を作成しました。@ 記号は、Windows PowerShell の配列演算子で、ハッシュテーブルは、キーと値のペアで構成される配列です。この場合、キーは作成するプロパティの名前で、値はプロパティに割り当てるコンテンツです。ハッシュテーブルの式の部分では、$_ 変数を使用して現在のパイプライン オブジェクトを参照できます。この例では、Last Name プロパティを取得しました (プロパティ名に空白文字が含まれているので、プロパティ名を二重引用符で囲む必要がありました)。

Select-Object コマンドでは、任意の数のプロパティ名を変更できます。

Import-CSV c:\new-users.csv | Select @{Name="Surname";Expression={$_."Last Name"}}, @{Name="GivenName";Expression={$_."First Name"}}

問題は、Select-Object コマンドでは、指定したものしか出力されないことです。つまり、1 ~ 2 つの列名を変更するように指定して、名前を変更した列と共に名前を変更していない列を出力することはできません。通常、出力する必要があるプロパティは、次のコマンドレットで指定する必要があります。もちろん、CSV ファイルの列名を変更する必要がなければ、CSV の列名をそのまま指定できます。

Import-CSV c:\new-users.csv | Select @{Name="Surname";Expression={$_."Last Name"}}, @{Name="GivenName";Expression={$_."First Name"}},Department,Organization,Name

この場合、Department、Organization、および Name プロパティは名前を変更することなく渡されます。これらは New-ADUser コマンドレットの関連付けられているパラメーターと完全に一致しているので名前を変更しなくても問題ありません。

指定する列数が多い場合には、面倒だと感じると思いますので、ショートカットをご紹介しましょう。

Import-CSV c:\new-users.csv | Select @{Name="Surname";Expression={$_."Last Name"}}, @{Name="GivenName";Expression={$_."First Name"}},*

* を指定すると、私が作成した Surname プロパティと GivenName プロパティと共に入力オブジェクトのすべてのプロパティが出力されます。CSV ファイルが次のような状態だとしましょう。

First Name,Last Name,Department,Name
Don,Jones,IT,DonJ
Greg,Shields,Janitorial,GregS
Jeff,Hicks,IT,JeffH

この場合は、次の 2 つのコマンドレットを使用できます。

Import-CSV c:\new-users.csv | Select @{Name="Surname";Expression={$_."Last Name"}}, @{Name="GivenName";Expression={$_."First Name"}},*

各出力オブジェクトには、First Name、Last Name、Department、Name、Surname、および GivenName という 6 つのプロパティが含まれます。つまり、出力オブジェクトには、オブジェクトに元々あったプロパティと私が追加したプロパティが含まれています。それから、このオブジェクトを New-ADUser コマンドレットに渡します。

Import-CSV c:\new-users.csv | Select @{Name="Surname";Expression={$_."Last Name"}}, @{Name="GivenName";Expression={$_."First Name"}},* | New-ADUser

First Name プロパティと Last Name プロパティは、New-ADUser コマンドレットのパラメーターと一致しないので、このコマンドレットでは、これらのプロパティについて何の処理を行うこともできません。ですが、問題ありません。このコマンドレットでは、バインドできないプロパティは無視し、残りの 4 つのプロパティ (この場合は、Surname、GivenName、Department、および Name) をパラメーターにバインドして、新しいユーザー アカウントを作成します。

習慣を変える

Windows PowerShell を使用するうえで最大の課題の 1 つとなるのは、決して諦めないことです。つまり、列名が必要としているものと一致しないことが、手元にある CSV ファイルを使用できない唯一の要因である場合、この問題を解決する方法が CSV ファイルを変更することだと思わないでください。Windows PowerShell では、ほとんどの場合、少しの調査を行えば必要な処理を行えます。

Windows PowerShell を使用する際に、どのような厄介な問題に直面しましたか。そのような問題について、ぜひお聞かせください。今後のコラムで、その問題の解決策をご紹介させていただくかもしれません。質問は、www.ConcentratedTech.com (英語) から投稿してください。このサイトでは、オンラインですぐに回答したり、皆さんから詳細な情報を収集して、今後の Microsoft TechNet Magazine コラムの題材にすることを検討させていただきます。

Don Jones は、米国内で最も熟練した Windows PowerShell の指導者およびスクリプト作成者の 1 人です。ConcentratedTech.com (英語) でブログを公開しており、Windows PowerShell に関するヒントを毎週紹介しています。このブログでは、Don に連絡したり、質問を投稿したりすることもできます。

関連コンテンツ