PowerShell
basicMenu
scriptbasic
Variables
operator
control
func
string
file
directory
path
xml
myfunction
oracle

01.インストール

PowerShellの実行には、Microsoft .NET Framework 2.0が必要です。
必要に応じて、入手/インストールしてください
PowerShellのインストーラはOSによって異なります。
・Windows 2003 ServerおよびWindows XP SP2は
http://support.microsoft.com/?kbid=926140
・Windows Vistaは
http://support.microsoft.com/?kbid=928439
から入手してください(2007/11/08時点)
ダウンロードしたファイルをダブルクリックしてインストーラの指示の従いインストールを行います。

02.起動と終了

PowerShellの起動は、[スタート] ボタンをクリックし、[すべてのプログラム] をクリックします。次に、[Windows PowerShell 1.0] をクリックし、[Windows PowerShell] アイコンをクリックします。
また、[ファイル名を指定して実行] ボックスから起動するには、[スタート]-[ファイル名を指定して実行] をクリックします。次に、「powershell」と入力し、[OK] をクリックします。
[コマンド プロンプト] (cmd.exe) ウィンドウから起動するには、コマンド プロンプトで「powershell」と入力します。
PowerShellを終了するには、コマンドライン上でexit[enter] と入力するか、右上の[X]ボタンをクリックします。

03.コマンドの入力と実行

PowerShellのコマンドはコマンドレットと呼ばれます。
Get-ChildItemというコマンドを実行してみましょう。
PS ~ > のあとに Get-ChildItemと入力し[Enter]キーを押します。
sample2のように表示されます。
Get-ChildItemコマンドは、コマンドプロンプトでいうところのDirコマンドに相当します。

sample1

PS C:\Documents and Settings\HIRO> Get-ChildItem
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\Users\HIRO
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2007/09/26 23:26 .gimp-2.2
d---- 2007/07/26 22:50 .VirtualBox
d---- 2007/06/14 22:50 AAA
-a--- 2007/06/23 23:05 619 _viminfo
コマンドプロンプトとの違いを見てみましょう。
コマンドプロンプトでの実行結果はsample3の用になります。

sample2

C:\Users\HIRO>dir
C:\Users\HIRO のディレクトリ
2007/10/31 19:40 <DIR> .
2007/10/31 19:40 <DIR> ..
2007/09/26 23:26 <DIR> .gimp-2.2
2007/07/26 22:50 <DIR> .VirtualBox
2007/06/14 22:50 <DIR> AAA
2007/06/23 23:05 619 _viminfo
PowerShellを終了するには
PS ~ > のあとに exitと入力し[Enter]キーを押します。
または、右上の[X]ボタンをクリックして終了します。

sample3

PS C:\Documents and Settings\HIRO> exit

04.コマンドの使用方法を調べるには

コマンドの使用方法を調べるには、
Get-Help <調べたいコマンド>
と入力し[Enter]キーをクリックします
Sample1では、Get-PSDriveコマンドの使用法を調べています

sample1

PS C:\Users\HIRO> Gett-Help Get-PSDrive
詳細を参照するには
Get-Help 調べたいコマンド -Detailed
と入力し[Enter]をクリックします。

sample2

C:\Users\HIRO> Get-Help Get-PSDrive -Detailed
技術情報を参照するには
Get-Help 調べたいコマンド -full
と入力し[Enter]をクリックします。

sample3

C:\Users\HIRO> Get-Help Get-PSDrive -full

05.特定のヘルプトピックを参照する

ワイルドカードを使用することで特定のヘルプトピックを参照することができます。
Get系のコマンド一覧だけを取得するには
Get-Help Get-*
と入力し[Enter]キーを押します。
Set系も同様のやり方で取得することが可能です

sample1

PS C:\Users\HIRO> Get-Help Get-*
Name Category Synopsis
---- -------- --------
Get-Command Cmdlet マンドレットおよびその他の Windows...
Get-Help Cmdlet Windows PowerShell のコマンドレット...
Get-History Cmdlet 現在のセッション中に入力したコマンド...
Get-PSSnapin Cmdlet コンピュータ上の Windows PowerShell ...
Get-EventLog Cmdlet ローカル イベント ログまたはこれらの...
Get-ChildItem Cmdlet 1 つ以上の指定された場所から項目およ...
以下省略

06.PowerShellで使えるショートカットキー

ショートカットキー 説明
[↑]キー 今までに入力したコマンドレットの履歴を過去方向へさかのぼって表示していきます。
[↓]キー 今までに入力したコマンドレットの履歴を未来方向へ表示していきます。
[PgUp]キー 一番最初に入力したコマンドを表示します
[PgDn]キー 一番最後に入力したコマンドを表示します
[→]キー 一番最後に入力したコマンドを一文字ずつ補完しながら表示します
[Home]キー コマンドラインの先頭へ移動します
[End]キー コマンドラインの最後尾へ移動します
[Ctrl]+[←]キー カーソルを単語単位で先頭方向へ移動させます
[Ctrl]+[→]キー カーソルを単語単位で後方方向へ移動させます
[Ctrl]+[c]キー 現在実行中のコマンドをキャンセルします
[F7]キー 今までに入力したコマンドの履歴をダイアログボックスで表示させ、矢印キーで選択、[Enter]キーで実行することができます
[Tab]キー 現在入力途中であるコマンドを補完して表示させます。[Tab]キーを何度も押すと、現在入力したところまでの文字列から推測できるコマンドの候補が次々表示されます

07.出力ウィンドをクリアする

Clear-Hostコマンドを使用すると、出力ウィンドウがクリアされます

sample1

PS C:\Users\HIRO> Clear-Host[Enter]

08.エイリアスについて

Windows Powerhellではエイリアスというメカニズムが使用され、ユーザーがコマンドを別名で参照できるようになっています。
たとえばClear-Hostコマンドはclsという別名を持っており、コマンドプロンプト上でclsと入力しても、Clear-Hostコマンドであることが認識され、実行が行われます。
Unixの代表的なコマンド chdir, diff, lsなど(ほかにも多数)もあらかじめエイリアスが設定されているものもあります。
また、PowerShellでは、略称を統一することによって一連の標準エイリアスが定義されています。
以下に略称の一覧(一部)を示します。
項目 略称
G et g
S et/td> s
G et- I tem gi
S et- I tem si
G et- L ocation gl
S et- L ocation sl
G et- C ommand gl
S et- C ommand sl

09.エイリアスを調べる

指定したコマンドのエイリアスを調べるには、Get-Aliasコマンドを使用します。
たとえば、Unixのlsコマンドのエイリアスを調べるには、sample1のように入力します。
DefinitionがPowerShellでのコマンドになります。

sample1

PS C:\Users\HIRO> Get-Alias ls
CommandType Name Definition
----------- ---- ----------
Alias ls Get-ChildItem
また、現在定義済みのエイリアス一覧を調べるにはAliasコマンドを使用します

sample2

PS C:\Windows> alias
CommandType Name Definition
----------- ---- ----------
Alias ac Add-Content
Alias asnp Add-PSSnapin
Alias clc Clear-Content
Alias cli Clear-Item
Alias clp Clear-ItemProperty
Alias clv Clear-Variable
:
以下省略...

10.新しいエイリアスを作成する

新しいエイリアスは
Set-Alias -Name 新しいエイリアス -Value エイリアス名をつけるコマンド
で作成することができます。
sample1では、Get-Helpコマンドにghというエイリアスを作成します
これ以降、ghと入力するとGet-Helpコマンドレットが実行されます。

sample1

C:\Users\HIRO> Set-Alias -Name gh -Value Get-Help

11.プログラムを起動するコマンドにエイリアスを作成する

プログラムを起動するコマンド(たとえばメモ帳や電卓)にエイリアスを作成するには、
Set-Alias エイリアス名 プログラムのパス
で作成することができます。
sample1は電卓に"den"というエイリアスを作成します
以降 den[Enter]と入力すると電卓が起動します。

sample1

PS C:\Users\HIRO> Set-Alias den calc

12.エイリアスを削除する

エイリアスを削除するには、Remove-Itemコマンドレットを使用します。
エイリアス ls を削除する場合には、sample1のように入力します

sample1

PS C:\Users\HIRO> remove-item alias:ls

13.PowerShellウィンドウ内でのコピー&ペースト

PowerShellウィンドウ内で文字列をコピーするには、コピーしたい文字列を選択しマウスを右クリックする。
コピーした文字列をペーストしたい場合は、コマンドライン上でマウスを右クリックする。

14.出力結果を1ページずつ表示させる

出力結果を1ページずつ表示させるには、Out-Hostコマンドレット(パラメータに-pagingを使用)を使用します。
たとえばGet-Commandコマンドレットの実行結果を1ページずつ表示させたい場合は、パイプライン(|)を使用してsample1のように入力します。 パイプラインは、パイプの左側の結果を右のコマンドへ受け渡します。
sample1の場合はGet-Commandの結果をOut-Hostコマンドへ引き渡します。 このときパラメータとして -paging があるので1ページずつ表示されることとなります。
次ページがある場合には
次のページ、 次の行、Q 終了
のように次の操作方法が表示されます。

sample1

PS C:\Users\HIRO> Get-Command | Out-Host -Paging
CommandType Name Definition
----------- ---- ----------
Cmdlet Add-Content Add-Content [-Path] <String[]> [-Value] <Object[...
Cmdlet Add-History   Add-History [[-InputObject] <PSObject[]>] [-Pass...
Cmdlet Add-Member Add-Member [-MemberType] <PSMemberTypes> [-Name]...
Cmdlet Add-PSSnapin Add-PSSnapin [-Name] <String[]> [-PassThru] [-Ve...
Cmdlet Clear-Content Clear-Content [-Path] <String[]> [-Filter <Strin...

省略
:
<Space> 次のページ、<CR> 次の行、Q 終了
more関数を使用しても、Out-Host -paging と同じ動作をします。
この場合は
Get-Command | more
と入力します

sample2

PS C:\Users\HIRO> Get-Command | more
CommandType Name Definition
----------- ---- ----------
Cmdlet Add-Content Add-Content [-Path] [-Value] Cmdlet Add-History   Add-History [[-InputObject]
] [-Pass...
Cmdlet Add-Member Add-Member [-MemberType]
[-Name]...
Cmdlet Add-PSSnapin Add-PSSnapin [-Name] [-PassThru] [-Ve...
Cmdlet Clear-Content Clear-Content [-Path] [-Filter
省略
:
次のページ、 次の行、Q 終了


15.出力結果をファイルに保存する

出力結果をファイルに保存するには、Out-Fileコマンドを使用します。
たとえばGet-Commandの実行結果をC:\CommandList.txtに保存する場合には、Sample1のように入力します。
書式は
実行するコマンド | Out-File -FilePath 出力先ファイルパス
既定では、Out-File コマンドレットによって作成されるファイルは Unicode ファイルですので注意が必要です。(ユーザーズガイドに記載)

sample1

PS C:\Users\HIRO> Get-Command | Out-File -FilePath C:\CommandList.txt
エンコードを指定するには
実行するコマンド | Out-File -FilePath 出力先ファイルパス -Encoding エンコードタイプ
とします。
エンコードタイプに指定可能な文字列は Unicode、UTF7、UTF8、UTF32、ASCII、BigEndianUnicode、Default、および OEM です。既定値はUnicode です。
sample1をAscii形式でファイルへ出力する場合はsample2のように入力します。

sample2

PS C:\Users\HIRO> Get-Command | Out-File -FilePath C:\CommandList.txt -Encoding Ascii

16.PowerShellにおけるドライブ

通常、「ドライブ」というとCドライブ、Dドライブなどファイルシステムにおけるドライブを想像されるのではないでしょうか?
Windows PowerShellにおけるドライブとは、Windows Powershell から、ファイル システムのドライブと同じようにアクセスすることのできるデータの保管場所です。
これには、従来通りのファイルシステム、エイリアス、レジストリ、関数などがあります。
Windows PowerShellがPowerShellドライブとして認識しているリストを取得するには、Get-PSDriveコマンドレットを使用します。
sample1は私のテスト環境で実行した例ですが、実行結果を見ると従来通りのファイルシステムのほかに、Aliasドライブ、certドライブ(証明書ストア)、HKCU(HKEY_CURRENT_USERレジストリ)、HKLM(HKEY_LOCAL_MACHINEレジストリ)などがあることを確認できます。

sample1

PS C:\Work2> Get-PSDrive
Name Provider Root CurrentLocation
---- -------- ---- ---------------
A FileSystem A:\
Alias Alias
C FileSystem C:\ Work2
cert Certificate \
D FileSystem D:\
E FileSystem E:\
Env Environment
Function Function
HKCU Registry HKEY_CURRENT_USER
HKLM Registry HKEY_LOCAL_MACHINE
T FileSystem T:\
U FileSystem U:\
V FileSystem V:\
Variable Variable
W FileSystem W:\
X FileSystem X:\
Y FileSystem Y:\
Z FileSystem Z:\
ではエイリアスやレジストリ等がドライブとして認識されると、どんなメリットがあるでしょうか?
たとえば、Get-ChildItemコマンドレットは、ファイルシステムで使用するとカレントディレクトリにあるファイルの一覧を取得することができます。
これをドライブがレジストリの場合にGet-ChildItemコマンドレットを使用すると、ファイルシステムの時と同様に現在のレジストリ項目の位置にある一覧を取得することができるようになります。
ファイルシステムであろうとレジストリであろうと、同様に操作することが可能となります。

sample2

PS HKCU:\> Get-ChildItem
Hive: Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER
SKC VC Name Property
--- -- ---- --------
2 0 AppEvents {}
0 36 Console {ColorTable00, ColorTable01, ColorTable02, ColorTable03...}
12 0 Control Panel {}
0 3 Environment {TEMP, TMP, DXROOT}
4 0 EUDC {}

17.PowerShellドライブを切り替えるには

PowerShellのドライブを切り替えるということは、現在の作業場所を指定した場所に変更すると言うことを意味します。
PowerShellのドライブを切り替えるには、Set-Locationコマンドレットを使用します。
Set-Location 切り替え先のドライブ名 :[Enter]
切り替え先のドライブ名のあとにコロン(:)を入力することを忘れないでください。
sample1ではCドライブへ移動します。

sample1

PS C:\Users\HIRO> Set-Location C:
PS C:\Users\HIRO>
sample2ではHKCUドライブ(レジストリの HKEY_CURRENT_USER)へ移動します。

sample2

PS C:\Users\HIRO> Set-Location HKCU:
PS HKCU:\>
移動したHKCUドライブで、Get-ChildItemコマンドレットを使用すると、HKEY_CURRENT_USERの下にあるアイテム一覧を取得することができます。

sample3

PS HKCU:\> Get-ChildItem
Hive: Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER
SKC VC Name Property
--- -- ---- --------
2 0 AppEvents {}
0 36 Console {ColorTable00, ColorTable01, ColorTable02, ColorTable03...}
12 0 Control Panel {}
0 3 Environment {TEMP, TMP, DXROOT}
4 0 EUDC {}
1 6 Identities {Identity Ordinal, Migrated7, Last Username, Last User ID...}
3 0 Keyboard Layout {}
0 0 Network {}
4 0 Printers {}
48 0 Software {}
1 0 System {}
0 1 SessionInformation {ProgramCount}
1 8 Volatile Environment {LOGONSERVER, USERDOMAIN, USERNAME, USERPROFILE...}

18.ドライブのルートへ移動する

ドライブのルートへ移動するには
Set-Location -Path .. -PassThru

と入力します。
sample1では C:\Work から C:\ へ移動します

sample1

PS C:\Work> Set-Location -Path .. -PassThru
Path
----
C:\
PS C:\>

01.スクリプトファイルの作成

Windows PowerShellでは、スクリプトファイルを作成することができます。
スクリプトファイルを作成するには、実行したいコードをテキストエディタを開いて入力し、拡張子をps1として保存します。
ただし、ps1ファイルはエクスプローラ等からダブルクリックしても実行されません。(メモ帳が開いてしまうはずです)
ps1ファイルはPowerShellから明示的に呼び出す必要があります。

02.セキュリティーポリシーを設定する

スクリプトファイル(*.ps1)を実行するには、セキュリティーポリシーがスクリプトの実行を許可する設定になっている必要があります。
セキュリティーポリシーは Get-ExecutionPolicy コマンドレットで確認することができます。
セキュリティーポリシーには下記のものがあります。
Restricted 構成ファイルの読み込みやスクリプトの実行を行いません。 既定値は "Restricted" です。 
AllSigned すべてのスクリプトと構成ファイルが信頼された発行元によって署名されていることを要求します (ユー ザーがローカル コンピュータに書き込むスクリプトを含む)。
RemoteSigned インターネットからダウンロードされたすべてのスクリプトおよび構成ファイルが、信頼された発行元によって署名されていることを要求します。
Unrestricted すべての構成ファイルを読み込み、すべてのスクリプトを実行します。 インターネットからダウンロ ードされた署名されていないスクリプトを実行する場合、スクリプトを実行する前に確認を求められます。
スクリプトの実行および開発が行えるよう、セキュリティーポリシー(ここではRemoteSigned)を設定します。
sample1 のように入力し、セキュリティーポリシーを設定してください、
注意) Windows Vistaでは「管理者として実行」でPowerShellを起動していない場合は、セキュリティポリシーの設定に失敗するようです。

sample1

PS C:\Users\HIRO > Set-ExecutionPolicy RemoteSigned
セキュリティーポリシーを設定したら、きちんと設定できているかをGet-ExecutionPolicyコマンドレットで確認します。

sample2

PS C:\Users\HIRO > Get-ExecutionPolicy
RemoteSigned

03.スクリプトファイルの実行

スクリプトファイル(*.ps1)を実行する方法として、PowerShellから明示的に呼び出す方法があります。
まずは、メモ帳を開いて
Get-ChildItem registry::hklm\software
と入力し、GetRegSoft.ps1 と名前を付け、任意のフォルダに保存してください。(ここではC:\Workへ保存することとします)
このコマンドは、HKEY_LOCAL_MACHINE\SOFTWARE キー内のレジストリキー全てを取得します。
コマンドラインに .\GetRegSoft.ps1[Enter]と入力してください。
HKEY_LOCAL_MACHINE\SOFTWARE のレジストリキーが取得されます。
PowerShellではスクリプトの実行は必ず絶対パスか相対パスである必要があります。
そのためスクリプトファイルの実行は
.\GetRegSoft.ps1[Enter]
または
.GetRegSoft.ps1[Enter]
または
C:\Work\GetRegSoft.ps1[Enter]
のように指定します。
GetRegSoft.ps1[Enter]では動かないことに注意してください。

sample1

PS C:\Work> .\GetRegSoft.ps1
Hive: Microsoft.PowerShell.Core\Registry::hklm\software
SKC VC Name Property
--- -- ---- --------
1 0 Acrobat Reader {}
2 0 Adobe {}
9 0 ahead {}
2 0 Analog Devices {}
1 0 Apple Computer, Inc. {}

以下省略

04.スクリプトファイルへ値を渡すには

PowerShellではスクリプトファイルへ値を渡すことができます。
渡された値は $args 変数へ格納されます。
まずは sample1のように入力し、test1.ps1 として保存してください。

sample1

$args[0]
$args[1]
次に
./test1.ps1 3 5
と入力し、スクリプトファイルへ"3"と"5"を渡してみます。
結果として"3"と"5"が返されます。
このようにスクリプトファイルに対し値を渡すことが可能です。

sample2

PS C:\Work> ./test1.ps1 3 5
3
5
次に、外部から2つの値受け取りを足し算する関数(Tashizan)を持つスクリプトファイルを作成してみます。
sample3のように入力し test2.ps1 として保存してください。
スクリプトファイルの中の
Tashizan $args[0] $args[1]
は、外部から受け取った値2つ($argsに格納される)を関数Tashizanへ渡しています。

sample3

function Tashizan ($x, $y){
return $x + $y
}
Tashizan $args[0] $args[1]
test2.ps1 の実行結果は sample4 のとおりです。
"3"と"5"を渡した結果、足し算が行われて"8"を返しています。

sample4

PS C:\Work2> ./test2.ps1 3 5
8

05.スクリプトファイルの結果を変数に受け取るには

まずは、sample1のように入力し、test1.ps1として保存します。
(足し算を行うスクリプトです)

sample1

function Tashizan ($x, $y){
return $x + $y
}
Tashizan $args[0] $args[1]
スクリプトの結果を受け取るには
$変数 = 実行するスクリプトファイル

とします。
先ほどのスクリプトを実行し、結果を受け取る例が sample2 です。
$result = ./test1.ps1 3 2
を実行したあとに
$resultの値を確認してみると、計算結果が格納されていることがわかります。

sample2

PS C:\Work2> $result = ./test1.ps1 3 2
PS C:\Work2> $result
5

01.変数を利用する

PowerShellで変数を利用するには
・先頭の文字を「$」とすること
・2文字目以降を英数字、またはアンダースコアとすること

という規則に従って命名する必要があります。
文字列を変数に代入するには 代入したい文字列をダブルクォーテーションで括って
変数 = " 代入したい文字列 "
とします。 sample1参照

sample1

PS C:\Users\HIRO> $a = "HIRO"
変数の中身を確認するには、変数名を書いて[Enter]キーを押します。

sample2

PS C:\users\HIRO> $a
HIRO
次に数値を代入してみます。
書式は
変数名 = 数値
です。 sample2参照

sample3

PS C:\Users\HIRO> $a = 3
現在の日時を変数に代入してみましょう。
現在の日時を取得するには、Get-Dateコマンドレットを使用します。
先ほどと同様に、 = の左辺に変数名を、右に代入する値を書きます。

sample4

PS C:\Users\HIROKI> $a = Get-Date
PS C:\Users\HIROKI> $a
2007年11月18日 21:57:33
このように、PowerShellでは型を宣言しなくても、値を代入することができます。
これは、PowerShellの変数が.NET Frameworkのオブジェクトであるためです。
オブジェクトには型があります。
現在の変数がどんな型になっているかを調べるにはGetTypeメソッドを使用します。
今までに入力した値が実際にどんな型になるかを示したのが sample5です。
このように、PowerShellでは右辺に書いた値によって、自動で型がセットされます。

sample5

PS C:\Users\HIROKI> $a = "HIRO"
PS C:\Users\HIROKI> $a.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
PS C:\Users\HIROKI> $a = 3
PS C:\Users\HIROKI> $a.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Int32 System.ValueType
PS C:\Users\HIROKI> $a = Get-Date
PS C:\Users\HIROKI> $a.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True DateTime System.ValueType

02.変数に型を指定する

PowerShellでは、明示的に型を指定する方法も準備されています。
書式は
[型] 変数名 = 値
です。sample1参照
GetTypeメソッドで確認すると、指定された型で作成され手いることがわかります。
型名に指定した"System."は省略して書くこともできます。
一例を挙げておきます
byte [byte] $a = 1
int [int] $a = 3
single [single] $a = 3
double [double] $a = 3.14159
string [string] $a = "HIRO"

sample1

PS C:\Users\HIRO> [System.String] $a = "HIRO"
PS C:\Users\HIRO> $a.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object

03.配列変数を使用する

配列変数を使用する

sample1

PS C:\Users\HIROKI> $a = 1,2,3,4,5
PS C:\Users\HIROKI> $a
1
2
3
4
5
ついでに変数 $a の型を確認してみます。
$a.GetType() [Enter] と入力してください。 (sample2)
Objectの配列型になっていることが確認できます。

sample2

PS C:\Users\HIRO> $a.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
配列の要素にアクセスするには
変数名[インデックス番号] とします。
インデックス番号は0から数えます。
sample3では変数 $a の要素番号2 の値を取得しています。

sample3

PS C:\Users\HIRO> $a[2]
3
また
変数名[取り出し開始位置要素番号..取り出し終了位置要素番号]
とすると範囲を指定して、値を取り出すことができます。
sample4 では 要素番号が1~3までの値を取得します。

sample4

PS C:\Users\HIRO> $a[1..3]
2
3
4
変数名[任意の要素番号,任意の要素番号, ....]
とすると指定した要素番号の値を取り出すことができます。
sample5 では 要素番号が1,2,4の値を取得しています。

sample5

PS C:\Users\HIRO> $a[1,2,4]
2
3
5
値を代入するには sample5(a[1]に5を代入)のようにします。

sample6

PS C:\Users\HIRO> $a[1] = 5

04.n次元配列を使用する

配列変数を使用する で、
変数名 = @(要素, 要素, 要素, .......)
で配列を作成することができることを示しました。
n次元配列では、これを利用して配列の中に配列を作成します。
つまり上で示した書式の要素に@(要素, 要素...)を含めることで、n次元配列を作成します。
sample1では要素数が2 x 2の配列を作成しています。
(1つ目の要素に@(1,2)を2つ目の要素に@(3,4)として配列を作成)

sample1

PS C:\Users\HIRO> $a = @(@(1,2), @(3,4))
n次元配列の各要素へアクセスするには、[]で要素番号を指定します。
([]の数は次元数によって変化します。)
sample2は sample1で代入したそれぞれの要素へアクセスする例です。

sample2

PS C:\Users\HIRO> $a[0][0]
1
PS C:\Users\HIRO> $a[0][1]
2
PS C:\Users\HIRO> $a[1][0]
3
PS C:\Users\HIRO> $a[1][1]
4
また、変数名[Enter] と入力すると、現在代入されている値すべてが表示されます

sample3

PS C:\Users\HIRO> $a
1
2
3
4
値を代入するには sample3(a[0][1]に5を代入)のようにします。

sample4

PS C:\Users\HIRO> $a[0][1] = 5

05.配列変数の要素数を取得する

配列変数の要素数を取得するには Length プロパティを使用します。
書式は
変数名.Length
です。
sample1では5個の数値を代入しているので、Lengthプロパティの値は5を返します。

sample1

PS C:\Users\HIRO> $a = 1,2,3,4,5
PS C:\Users\HIRO> $a.Length
5
次にn次元配列の場合を見てみましょう。
sample2では2次元配列として値を代入しています。
$a.Length[Enter] とした場合には"2"を返してきます。
これは、$aに代入した値が、@(1,2,3)と@(4,5,6)の2つだからです。
次に $a[0].Length[Enter] と入力した場合ですが、$a[0] は @(1,2,3)のことなので結果として"3"を返します。
同様に$a[1].Length[Enter]とした場合も3を返します。

sample2

PS C:\Users\HIRO> $a=@(@(1,2,3),@(4,5,6))
PS C:\Users\HIRO> $a.Length
2
PS: C:\Users\HIRO> $a[0].Length
3
PS: C:\Users\HIRO> $a[1].Length
3
任意の範囲を指定した場合でも要素数を取得することができます。
sample3の1つ目は要素番号が3~6までの要素数を返します。
2つめは5この要素を指定して(0,2,4,6,8)いるので5を返します。

sample3

PS C:\Users\HIRO> $a = 1,2,3,4,5,6,7,8,9,10
PS C:\Users\HIRO> $a[3..6].Length
4
PS C:\Users\HIRO> $a[0,2,4,6,8].Length
5

06.連想配列変数(ハッシュテーブル)を使用する

連想配列変数を使用するには
変数名 = @{キー名 = 値; キー名 = 値; ....... }

とします。(sample1)

sample1

PS C:Users\HIRO> $a = {Elephant="象",Tiger="虎",Snake="蛇"}
連想配列に代入されている値を確認するには
変数名[Enter] と入力します
または
変数名.キー名
とします。

sample2

PS C:Users\HIRO> $a
Elephant="象",Tiger="虎",Snake="蛇"
連想配列にアクセスするには
変数名["キー名"]
または
変数名.キー名

とします。

sample3

PS C:Users\HIRO> $a["Tiger"]

PS C:Users\HIRO> $a.Tiger

値を代入するには

変数名["キー名"] = 値

または
変数名.キー名 = 値
とします。

sample4

PS C:Users\HIRO> $a["Tiger"] = "とら"
PS C:Users\HIRO> $a.Tiger = "トラ"
また、変数名[Enter] と入力すると、現在代入されている値すべてが表示されます

sample5

PS C:\Users\HIRO> $a
Name Value
---- -----
Tiger 虎
Snake 蛇
Elephant 象

07.ブール値を変数に代入する

PowerShellでは、ブール値を$TRUE, $FALSEで表します。
TRUEを代入する場合は
変数名 = $TRUE
FALSEを代入するには
変数名 = $FALSE
とします。
代入後にGetTypeメソッドで型を確認すると、Booleanとなっていることがわかります。

sample1

PS C:\Users\HIRO> $b = $TRUE
PS C:\Users\HIRO> $b.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Boolean System.ValueType

08.コメントを使用する

コメントとは、コードの中に人間のために覚書として挿入する注釈のことです。
PowerShellでは #の文字以降、改行コードが現れるまでをコメントととして扱います。
(文字列としてダブルクォーテーションの内側に記述された場合はコメントではなく文字として扱われます)

sample1

PS C:\Users\HIRO> $PI = 3.1415 #円周率を設定
sample2 の場合は #がダブルクォーテーションの内側にあるので文字として扱われます

sample2

PS C:\Users\HIRO> $a = "#はダブルクォーテーションの内側に記述された場合は文字です"

09.16進数値を代入する

16進数値を代入するには、16進数で表した数値の先頭に "0x"を付けます。
sample1では 0x0f (10進数で15)を代入しています。

sample1

PS C:\Users\HIRO> $a = 0x0f
PS C:\Users\HIRO> $a
15

10.指数値を代入する

指数値を代入するには、文字"e"と10の倍数を表す値を指定する必要があります。
e3 は10の3乗 = 1000
e4 は10の4乗 = 10000
e5 は10の5乗 = 100000
といった感じです。
3.14を1000倍したい場合は sample1のように 3.14e3 とします

sample1

PS C:\Users\HIROKI> $a = 3.14e3
PS C:\Users\HIROKI> $a
3140

11.バイト(byte)計算する

PowerShellではキロバイト(KB)、メガバイト(MB)、ギガバイト(GB)の単位を認識します。
1KB[Enter] と入力するとバイト単位に直した値が表示されます。
MBやGBの単位も同様にバイト単位に直した値が表示されます。
注意:テラバイトは認識しないようです。

sample1

PS C:\Users\HIRO> 1KB
1024
PS C:\Users\HIRO> 1MB
1048576
PS C:\Users\HIRO> 1GB
1073741824
下記に示すように四則計算も可能です。

sample2

PS C:\Users\HIRO> 1GB / 256MB
4
PS C:\Users\HIRO> 1MB / 256KB
4
PS C:\Users\HIRO> 1MB / 128KB
8

12.不要になった変数を削除する

PowerShellで変数を利用するには という規則に従って命名する必要があります。
PowerShellのコンソールで一度変数を作成してしまうと、PowerShellを終了するまでその変数は残ってしまいます。
Remove-Variableコマンドレットを使用すると、任意のタイミングで指定した変数とその値を削除することができます。
書式は
Remove-Variable 変数名
です。
このとき変数名の指定には List1のように$を外した形で指定する必要があります

List1

PS C:\Work> Remove-Variable a

01.算術演算子

PowerShellで使用可能な算術演算子には下記のものがあります。
+ 2つの値を加算する
- 一方の値から他方の値を減算する
- 値を負の数値に変換する
* 2つの値を乗算する
/ 2つの値で除算を行う
% 除算で発生した余りを返す
また算術演算子には優先順位があります
1. - (負の数を表すマイナス記号)
2. *, /, %
3. +、- (減算を表すマイナス記号)
※かっこを使用して特定の部分を囲むと演算子の優先順位を変更することができます
2 + 8 / 2 * 3 はどうのように計算されるかというと
まず始めに 8 / 2 が計算されて4が返ってきます。
次にこの4と3を掛けます。 4 * 3 で12を返します。
最後に 2 に 先ほどの12が加算され、答えが14となります。

sample1

PS C:\Users\HIRO> 2 + 8 / 2 * 3
14
次に、かっこを使用して演算子の順位を変えた例を示します。
(1 + 2) * ( 3 + 4 ) は
最初に、はじめのかっこの 1 + 2 が計算されて3となります。
次に、2番目のかっこの 3 + 4が計算されて7となります。
最後に、3 * 7 を計算して21となります。
かっこのない状態で計算すると
1 + 2 * 3 + 4
最初に2 * 3で6
次に 1 + 6 + 4を計算し11となります

sample2

PS C:\Users\HIRO> (1 + 2) * ( 3 + 4 )
21
PS C:\Users\HIRO> 1 + 2 * 3 + 4
11

02.代入演算子

代入演算子は変数に単一の値 (スカラ) または複数の値 (配列) を代入するために使用します。
代入演算子には下記のものがあります。
= 指定した値を変数の値に設定します。
+= 指定した値を変数の値に加算するか、指定した値を既存の値に追加します。
-= 指定した値を変数の値から減算します。
*= 指定した値で変数の値を乗算するか、指定した値を既存の値に追加します。
/= 指定した値で変数の値を除算します。
%= 指定した値で変数の値を除算し、余り (法) を変数に代入します。
= 代入演算子
単一の値を代入するには
変数名(先頭が$で始まる) = 値
という書式で行います。
sample1では、$aに数値、$bに文字列(値を2重引用符で囲む)、$cに文字列の配列(カンマで区切ることで配列となる)代入しています

sample1

PS C:\Users\HIRO> $a = 3
PS C:\Users\HIRO> $a
3
PS C:\Users\HIRO> $b = "HIRO"
PS C:\Users\HIRO> $b
HIRO
PS C:\Users\HIRO> $c = "VB.NET", "C#", "PowerShell"
PS C:\Users\HIRO> $c
VB.NET
C#
PowerShell
+= 代入演算子
+=代入演算子は、変数の値を増加(インクリメント)または追加します。
$a += 3 と記述した場合、この式は $a = $a + 3 と同等です。
$a に 2が代入されている場合は、この式の結果は 5となります。
また、文字(列)の場合は、追加をします。
たとえば $b に"Hel" が代入されている場合
$b = $b + "lo" は "Hello"を返します。

sample2

PS C:\Users\HIRO> $a = 2
PS C:\Users\HIRO> $a += 3
PS C:\Users\HIRO> $a
5
PS C:\Users\HIRO> $b = "Hel"
PS C:\Users\HIRO> $b += "lo"
PS C:\Users\HIRO> $b
Hello
-= 代入演算子
-=代入演算子は、変数の値を減少(デクリメント)します。
この演算子は文字列には使用することができないことに注意してください。
$a -= 3 と記述した場合、この式は $a = $a - 3 と同等です。
$a に 5が代入されている場合は、この式の結果は 2となります。

sample3

PS C:\Users\HIROKI> $a = 5
PS C:\Users\HIROKI> $a -= 3
PS C:\Users\HIROKI> $a
2
*= 代入演算子
*=代入演算子は、演算子の右側に記述した値で乗算を行います。
$a *= 3 と記述した場合、この式は $a = $a * 3 と同等です。
$a に 5が代入されている場合は、この式の結果は 15となります。
文字列の場合には、演算子の右側に記述した値の文だけ文字列が繰り返されます。

sample4

PS C:\Users\HIRO> $a = 5
PS C:\Users\HIRO> $a *= 3
PS C:\Users\HIRO> $a
15
PS C:\Users\HIRO> $b = "Hello"
PS C:\Users\HIRO> $b *= 3
PS C:\Users\HIRO> $b
HelloHelloHello
/= 代入演算子
/=代入演算子は、演算子の右側に記述した値で除算を行います。
この演算子は文字列には使用することができないことに注意してください。
$a /= 3 と記述した場合、この式は $a = $a / 3 と同等です。
$a に 6が代入されている場合は、この式の結果は 2となります。

sample5

PS C:\Users\HIRO> $a = 6
PS C:\Users\HIRO> $a /= 3
PS C:\Users\HIRO> $a
2
%= 代入演算子
/=代入演算子は、演算子の右側に記述した値で除算を行い、余りを代入します。
この演算子は文字列には使用することができないことに注意してください。
$a %= 3 と記述した場合、この式は $a = $a % 3 と同等です。
$a に 7が代入されている場合は、この式の結果は 1となります。

sample6

PS C:\Users\HIRO> $a = 7
PS C:\Users\HIRO> $a %= 3
PS C:\Users\HIRO> $a
1

03.論理演算子

PowerShellで使用できる論理演算子は以下のものがあります。
演算子 説明
-and 論理積
-or 論理和
-not 論理否定
! 論理否定
-and 演算子
-and 演算子は、2 つの引数を評価し、両方の引数が真であるときのみ、True を返します。
たとえば
$a = (2 -gt 1) -and (5 -gt 2)
これは
「2は1より大きい且つ5は2より大きい」を$aに代入します。
この式は満たされるのでTrueとなります。

sample1

PS C:\Users\HIRO> $a = (2 -gt 1) -and (5 -gt 2)
PS C:\Users\HIRO> $a
True
-or 演算子
-or 演算子は、2 つの引数を評価し、どちらか一方または両方の引数が真であるときに、True を返します。
たとえば
$a = (2 -gt 1) -or (5 -gt 2)
これは
「2は1より大きい または 5は2より大きい」を$aに代入します。
この式は満たされるのでTrueとなります。
$a = (1 -gt 2) -or ( 2 -gt 5)
「1は2より大きい または 5は2より大きい」を$aに代入します。
この式は両方とも満たされないのでFalseとなります

sample2

PS C:\Users\HIRO> $a = (2 -gt 1) -or (5 -gt 2)
PS C:\Users\HIRO> $a
True
PS C:\Users\HIRO> $a = (1 -gt 2) -or (2 -gt 5)
PS C:\Users\HIRO> $a
False
-not演算子 および !演算子
-not演算子および!演算子は、式が偽かどうかを評価します。つまり式がTrue の場合はFalseを、式がFalseの場合にはTrueを返します。
たとえば
$a = -not (2 -gt 1)
これは
「2は1より大きい」の式が偽であるかを評価し$aに代入します。
この式は満たされる(真)のでFalseが代入されます。

sample3

PS C:\Users\HIRO> $a = -not (2 -gt 1)
PS C:\Users\HIRO> $a
False

04.比較演算子

PowerShellで値を比較するために使用できる演算子には下記のものがあります。
演算子 説明
-eq 等しい
-ne 等しくない
-gt より大きい
-ge 以上
-lt より小さい
-le 以下
-like ワイルドカードによる比較
-notlike ワイルドカードによる比較
-match 正規表現による比較
-nomatch 正規表現による比較
上記は大文字と小文字を区別しません。(上記演算子名の前に文字iを付けて-ieqとした場合も大文字と小文字を区別しません)
大文字と小文字を区別する場合は上記演算子名の前に文字cを付けて -ceq のようにします。
-eq演算子
この演算子は"等しい"( eq ual)を意味します。
この演算子の左側の値と右側の値が等しいかを比較します。
等しい場合にはTrueを返します。

sample1

PS C:\Users\HIRO> 5 -eq 5
True
PS C:\Users\HIRO> 5 -eq 3
False
-ne演算子
この演算子は"等しくない"( n ot e qual)を意味します。
この演算子の左側の値と右側の値が等しくないことを比較します。
等しくない場合にはTrueを返します。

sample2

PS C:\Users\HIRO> 5 -ne 3
True
PS C:\Users\HIRO> 3 -ne 3
False
-gt演算子
この演算子は"等しくない"( g reater t han)を意味します。
この演算子の左側の値が右側の値より大きいかを比較します。
右側の値より大きい場合にはTrueを返します。

sample3

PS C:\Users\HIRO> 5 -gt 3
True
PS C:\Users\HIRO> 3 -gt 5
False
-ge演算子
この演算子は"以上"( g reater or e qual)を意味します。
この演算子の左側の値が右側の値以上かを比較します。
右側の値以上の場合にはTrueを返します。

sample4

PS C:\Users\HIRO> 3 -ge 2
True
PS C:\Users\HIRO> 3 -ge 3
True
PS C:\Users\HIRO> 3 -ge 4
False
-lt演算子
この演算子は"より小さい"( l ess t han)を意味します。
この演算子の左側の値が右側の値より小さいかを比較します。
右側の値より小さい場合にはTrueを返します。

sample5

PS C:\Users\HIRO> 3 -lt 4
True
PS C:\Users\HIRO> 4 -lt 3
False
-le演算子
この演算子は"以下"( l ess or e qual)を意味します。
この演算子の左側の値が右側の値以下かを比較します。
右側の値以下の場合にはTrueを返します。

sample6

PS C:\Users\HIRO> 2 -le 3
True
PS C:\Users\HIRO> 3 -le 3
True
PS C:\Users\HIRO> 4 -le 3
False
-like演算子
この演算子はワイルドカードによる曖昧検索を行います。
曖昧検索にヒットした場合はTrueを返します。
sample7の1つ目は"HIRO's.NET"の先頭が"HIRO"で始まっているかを検索します。
2つ目は"hi"で始まっているかを検索します。
3つめは演算子名の先頭に"c"を付加して、大文字と小文字を区別して検索を行うためFalseが返されています。

sample7

PS C:\Users\HIRO> "HIRO's,NET" -like "HIRO*"
True
PS C:\Users\HIRO> "HIRO's,NET" -like "hi*"
True
PS C:\Users\HIRO> "HIRO's,NET" -clike "hi*"
False
-match演算子
この演算子は正規表現による検索を行います。
マッチした場合はTrueを返します。

sample8

PS C:\Users\HIRO> "HIRO's.NET" -match "[a-z]IRO's.NET"
True
-notmatch演算子
この演算子は正規表現による検索を行います。
マッチしなかった場合はTrueを返します。

sample9

PS C:\Users\HIRO> "HIRO's.NET" -notmatch "[a-z]IRO's.NET"
False

05.範囲演算子

範囲演算子を使用すると、ステートメント内で使用できる値の範囲を指定することができます。
範囲演算子は2つのピリオド(..)で表現されます。
範囲演算子は、
範囲の開始値..範囲の終了値
のように記述します。
sample1では ループするごとに $cnt に1~5の値が入ります。
Write-Host $cnt でコンソールへ結果を出力しています。

sample1

PS C:\Users\HIRO> foreach ( $cnt in 1..5 )
>> {
>> Write-Host $cnt
>> }
>>
1
2
3
4
5

06.置換演算子

置換演算子は、指定した値で元の値の一部または全体を置き換えることができます。
置換演算子は下記に示すように3つあります。
文字を置換するという意味では一緒ですが、大文字/小文字の区別をするかどうかで使用する演算子が異なることに注意してください。
演算子 大文字/小文字
-replace 区別しない
-ireplace 区別しない
-creplace 区別する
置換演算子の書式は
"置換対象文字列" -replace "置換したい文字(列)", "置換後の文字(列)"
"置換対象文字列" -ireplace "置換したい文字(列)", "置換後の文字(列)"
"置換対象文字列" -creplace "置換したい文字(列)", "置換後の文字(列)"
sample1の1つ目は -replace演算子を使用して、文字列"HIRO"に含まれてる文字"I"を"E"に置換しています。
2つめは文字列 "HIROI" に含まれている文字"I" を "E"に置換しています。
"HIROI" には "I" が2箇所あるので結果として "HEROE" が返されます

sample1

PS C:\Users\HIRO> "HIRO" -replace "I","E"
HERO
sample2では、演算子 -ireplace を使用して文字列の置換を行っています。
1つ目は小文字の "i" を "E" に置換しようとしていますが、文字列 "HIRO" には小文字の"i"が含まれていないので、置換されずに値が返されます。
2つ目は大文字の "I" を "E" に置換するので、"HERO" と置換された値が返ります。

sample2

PS C:\Users\HIRO> "HIRO" -creplace "i","E"
HIRO
PS C:\Users\HIRO> "HIRO" -creplace "I","E"
HERO

07.ビット演算子

ビット演算子は、ビットの比較によって生成された値を返します。
ビット演算子には下記のものがあります。
演算子 説明
-band ビット AND
-bor ビット OR
-band演算子
-band演算子は、ビットの AND 計算を行い、結果を10進数値で返します。
sample1では "10"と"12"のビットのAND計算を行った結果を返しています。
1010 (10)
AND 1100 (12)
-------------
1000 (8)

sample1

PS C:\Users\HIRO> 10 -band 12
8
-bor演算子
-bor演算子は、ビットの OR 計算を行い、結果を10進数値で返します。
sample1では "10"と"12"のビットのOR計算を行った結果を返しています。
1010 (10)
OR 1100 (12)
-------------
1110 (14)

sample2

PS C:\Users\HIRO> 10 -bor 12
13

08.型演算子

型演算子を使用すると、指定した値の型を判定することができます。
型演算子には下記のものがあります。
演算子 説明
-is 指定された型である
-isnot 指定された型ではない
型演算子の書式は
判定したい値 -is [ ]
判定したい値 -isnot [ ]
sample1の1つめは、数値の"3"がint型であるかを確認しています。
2つめは数値の"3"がstring型であるかを確認しています。

sample1

PS C:\Users\HIRO> 3 -is [int]
True
PS C:\Users\HIRO> 3 -is [string]
False
sample2の1つめは、数値の"3"がint型でないことを確認しています。
(int型なのでFalseを返します)
2つめは数値の"3"がstring型でないことを確認しています。
(数値の"3"はint型なのでTrueを返します)

sample2

PS C:\Users\HIRO> 3 -isnot [int]
False
PS C:\Users\HIRO> 3 -isnot [string]
True

09.束縛演算子

束縛演算子を用いると、コレクションの中に指定した値が含まれているかどうかを確認することができます。
演算子 説明
-contains コレクションに指定した値が含まれている(大文字/小文字を区別しない)
-notcontains コレクションに指定した値が含まれていない(大文字/小文字を区別しない)
演算子の先頭に"i"をつけた場合(-icontains および -inotcontains)と先頭に何も文字を付加しない場合(-contains, -notcontains)は大文字と小文字を区別しません。
演算子の先頭に"c"を付けた場合は(-ccontains, -cnotcontains)大文字と小文字を区別します。
sample1の1つ目は 数値1,2,3,4,5のいずれかに 3を含んでいるかを評価します。
2つ目は 数値1,2,3,4,5のいずれかに 7を含んでいるかを評価します。
3つ目は 文字列"HIRO","BANANA","GRAPES"のいずれかに、"BANANA"が含まれているかを評価します。
4つ目は 文字列"HIRO","BANANA","GRAPES"のいずれかに、"APPLE"が含まれているかを評価します。

sample1

PS C:\Users\HIRO> 1,2,3,4,5 -contains 3
True
PS C:\Users\HIRO> 1,2,3,4,5 -contains 7
False
PS C:\Users\HIRO> "HIRO","BANANA","GRAPES" -contains "BANANA"
True
PS C:\Users\HIRO> "HIRO","BANANA","GRAPES" -contains "APPLE"
False
sample1の1つ目は 数値1,2,3,4,5のいずれかに 3を含まれていないことを評価します。
2つ目は 数値1,2,3,4,5のいずれかに 7を含まれていないことをを評価します。
3つ目は 文字列"HIRO","BANANA","GRAPES"のいずれかに、"BANANA"が含まれていないことを評価します。
4つ目は 文字列"HIRO","BANANA","GRAPES"のいずれかに、"APPLE"が含まれていないことを評価します。

sample2

PS C:\Users\HIRO> 1,2,3,4,5 -notcontains 3
False
PS C:\Users\HIRO> 1,2,3,4,5 -notcontains 7
True
PS C:\Users\HIRO> "HIRO","BANANA","GRAPES" -notcontains "BANANA"
False
PS C:\Users\HIRO> "HIRO","BANANA","GRAPES" -notcontains "APPLE"
True

10.単項演算子

単項演算子には以下のようなものがあります。
演算子 説明
++ インクリメント
--/td> デクリメント
+ 正の数を表す
- 負の数を表す
++演算子
++演算子は、変数の値を1増加させます

sample1

PS C:\Users\HIRO> $a = 1
PS C:\Users\HIRO> $a++
PS C:\Users\HIRO> $a
2
--演算子
--演算子は、変数の値を1減少させます

sample2

PS C:\Users\HIRO> $a = 1
PS C:\Users\HIRO> $a--
PS C:\Users\HIRO> $a
0
+演算子
+演算子は、正を表します

sample3

PS C:\Users\HIRO> $a =1
PS C:\Users\HIRO> +$a
1
-演算子
-演算子は、負を表します

sample4

PS C:\Users\HIRO> $a = 1
PS C:\Users\HIRO> -$a
-1

01.ifステートメント

if ステートメントは、指定した条件がTrueとして評価された場合にコードブロックを実行します。
Falseで評価された場合に、実行するコードブロックと追加することも可能です。
構文は下記の通りです。
if (条件1)
{コード ブロック1}
[elseif (条件2)
{コード ブロック2}]
[else
コード ブロック3}]

"["~"]"までは省略可能です。
もっとも単純な if だけの例をsample1に示します。
if で変数 $a の値が3に等しいかを評価し、Trueであれば"$aは3です"と表示します。

sample1

PS C:\Users\HIRO> if ($a -eq 3) {
>> Write-Host '$aは3です'
>> }
>>
$aは3です
次にelse ステートメントを使用して、sample1を改良します。
$a が"3"と等しくない場合には "$a は3ではありません"と表示するようにします。

sample2

PS C:\Users\HIRO> if ($a -eq 3) {
>> >> Write-Host '$aは3です'
>> >> } else {
>> Write-Host '$aは3ではありません'
>> }
>>
$aは3ではありません
次にelseif ステートメントを使用した例を示します。
(sample3はsample1を改良したものです)
$a が負の数である場合には "$a は負です"と表示するようにします。
$a が負でも"3"でもない場合には"$aは3以外の正の数です"と表示します。

sample3

PS C:\Users\HIRO> if ($a -eq 3) {
>> Write-Host '$aは3です'
>> } elseif ($a -lt 0) {
>> Write-Host '$aは負です'
>> } else {
>> Write-Host '$aは3以外の正の数です'
>> }
>>
$aは負です

02.switchステートメント

switchステートメントを使用すると、複数のifステートメントを処理することができます。switchステートメントは事実上の一連のif ステートメントです。 式と各条件を個別に照合し、一致するものが見つかると、その条件に関連づけられたアクションが実行されます。
sample1 では 変数 $a の値が 3 のときに "$aは3です"と表示します。
switchステートメントは上から順に評価していきます。
$a が 1 かどうかを評価し、偽なので次の行へ
$a が 2 かどうかを評価し、偽なので次の行へ
$a が 3 かどうかを評価し、3なので(真){}の中の Write-Host "$a は 3です" を実行します。

sample1

PS C:\Users\HIRO> $a = 3
PS C:\Users\HIRO> switch ($a) {
>> 1 { Write-Host "$a は 1です" }
>> 2 { Write-Host "$a は 2です" }
>> 3 { Write-Host "$a は 3です" }
>> 4 { Write-Host "$a は 4です" }
>> 5 { Write-Host "$a は 5です" }
>> }
>>
3 は 3です
default句
sample2では、どの値にも該当しなかった場合の処理を追加しています。
変数 $a に -3を入れておいて、上から順に評価を行っていきます。
1, 2, 3 と評価していき、該当する値がないときに、"該当する値がありません" と表示しています。
default句を使用すると、どの値にも該当しなかった場合の処理を行うことができます。

sample2

PS C:\Users\HIRO> $a = -3
PS C:\Users\HIRO> switch ($a) {
>> 1 { Write-Host "$a は 1です" }
>> 2 { Write-Host "$a は 2です" }
>> 3 { Write-Host "$a は 3です" }
>> default { Write-Host "該当する値がありません" }
>> }
>>
該当する値がありません
break キーワード
一致するものが複数見つかった場合には、一致ごとに式が実行されます。
これを回避するには、breakキーワードを使用します。
breakキーワードは、これ以上処理が行われず、switch ステートメントが終了することを意味します。

sample3

PS C:\Users\HIRO> $a = -3
PS C:\Users\HIRO> switch ($a) {
>> -1{ Write-Host "$a は -1です"; break }
>> -2{ Write-Host "$a は -2です"; break }
>> -3{ Write-Host "$a は -3です"; break }
>> default{ Write-Host "該当する値はありませんでした"; break }
>> }
>>
-3 は -3です
-casesensitive オプション
-casesensitiveオプションは、一致する句が文字列の場合は、大文字と小文字を区別します。文字列でない場合はこのオプションは無視されます。

sample4

PS C:\Users\HIRO> $a = "HIRO"
PS C:\Users\HIRO> switch -casesensitive ($a) {
>> "hiro" { Write-Host "hiro に一致しました" }
>> "HIRO" { Write-Host "HIRO に一致しました" }
>> default{ Write-Host "一致しませんでした" }
>> }
>>
HIRO に一致しました
-wildcard
-wildcardオプションはワイルドカードを使って一致判定を行います。

sample5

PS C:\Users\HIRO> $a = "HIRO"
PS C:\Users\HIRO> switch -wildcard ($a) {
>> "HI*O" { Write-Host "HI*Oに一致しました" }
>> default { Write-Host "一致しませんでした"}
>> }
>>
HI*Oに一致しました
-regex オプション
-regexオプションを使用すると正規表現を使って一致判定を行います。

sample6

PS C:\Users\HIRO> $a = "HIRO"
PS C:\Users\HIRO> switch -regex ($a) {
>> "^H.*" { Write-Host "先頭がHです" }
>> default { Write-Host "HIROではありません" }
>> }
>>
先頭がHです

03.whileステートメント

while ステートメントは、指定した条件がTrueの間、コマンドブロック内のコマンドをループしながら実行します。
構文は下記の通りです。
while (<条件>){<コマンド ブロック>}
次の例は、$iCntが5より小さい間(-lt)ループします。
最初は、$iCntの初期値が0なので
「$iCntが5より小さいか」をチェックし、満たされる(真)のではコマンドブロックの中のコードを実行します。
2回目は、$iCntの値が1となり、「$iCntが5より小さいか?」を満たすので、コマンドブロックの中のコードを実行する、というように条件が満たされている間ループし続けます。

sample1

PS C:\Users\HIRO> $iCnt = 0
PS C:\Users\HIRO> while ($iCnt -lt 5)
>> {
>> $iCnt++
>> Write-Host $iCnt
>> }
>>
1
2
3
4
5
break を使って中断する
breakを使用すると、条件が満たされている間でも処理を中断し、ループを抜けることができます。
下記の例は、「$iCntが5より小さい間ループする」という条件ですが、コマンドブロックの中で if文を使用し、$iCntが3以上の場合に break を使用し、処理を中断しています。

sample2

PS C:\Users\HIRO> $iCnt = 0
PS C:\Users\HIRO> while ($iCnt -lt 5)
>> {
>> $iCnt++
>> if ( $iCnt -gt 3 ) { break }
>> else { Write-Host $iCnt}
>> }
>>
1
2
3

04.forステートメント

forステートメントは、指定した条件がTrueの間、コマンドブロック内のコマンドを実行するループを作成するための言語構造です。
構文は下記の通りです。
for (<初期化>; <条件>; <繰り返し処理>)
{<コマンド ブロック>}

C#での
for ( i = 0; i < 5; i++ )
{
Console.WriteLine(i.ToString());
}
は下記のように記述します。

sample1

PS C:\Users\HIRO> for ( $i = 0; $i -lt 5; $i++ )
>> {
>> Write-Host $i
>> }
>>
0
1
2
3
4

05.foreachステートメント

foreach ステートメントは、項目のコレクションに含まれるすべての項目を順番に処理するための言語コマンドです。
構文は下記の通りです。
foreach ($<項目> in $<コレクション>)
{<コマンド ブロック>}

sample1では、foreach ループでは、$weekday という配列の値が表示されます。
$weekdayから値が1つずつ取り出され、$wに代入され、Write-Hostコマンドレットで$wの値が表示されます。

sample1

PS C:\Users\HIRO> $weekday = "Mon","Tue","Wed","Thu","Fri"
PS C:\Users\HIRO> foreach ($w in $weekday)
>> {
>> Write-Host $w
>> }
>>
Mon
Tue
Wed
Thu
Fri
Foreach ステートメントは、項目のコレクションを返すコマンドレットと共に使用することもできます。
sample2では、Get-Serviceコマンドから返される項目でStatusが"Running"になっているもののサービス名を表示します。

sample2

PS C:\Users\HIRO> foreach ( $s in Get-Service )
>> {
>> if ($s.Status -eq "running")
>> {
>> Write-Host $s.ServiceName
>> }
>> }
>>
PowerShell では、コマンド パイプライン内に foreach が現れると、Foreach- Object を呼び出す foreach エイリアスが使用されます。
パイプラインで foreach を使用するときの構文は次のとおりです。
<コマンド> | foreach {<コマンド ブロック>}
sample3はsample2と同じ結果を返します。

sample3

PS C:\Users\HIRO> Get-Service | foreach {
>> if ( $_.Status -eq "running")
>> {
>> Write-Host $_.ServiceName
>> }
>> }
>>

06.Doステートメント

PowerShellのDoステートメントには
Do .. While と Do .. Untilがあります。
はじめにDo .. Whileを説明します。
Do .. While は
1)Doの直後に書かれた{ }の中身を実行する
2)Whileに書かれている条件が(真)の間ループ
という動作を行います
構文は下記のとおりです
Do
{
繰り返し実行したい処理
}
While (条件式)

sample1のように入力し、DoWhile.ps1 と名前を付けて保存してください。
このスクリプトは
$a を0で初期化し、Doの中で変数の値を表示(Write-Host)するようにしています。
変数の値を表示した後は、$aをインクリメントします。
最後の行の While で変数 $a が 5未満(-lt)かを判定し、5未満の場合はループを続けます。

sample1

$a = 0
Do
{
Write-Host $a
$a += 1
}
while ( $a -lt 5 )
では、sample1を実行してみましょう。
実行結果はsample2のとおりです。
5回のループが行われるので、0~4の数値が表示されていることがわかります。

sample2

PS C:\Work> ./DoWhile.ps1
0
1
2
3
4
次にDo .. Untilですが、Untilからわかるように、指定した値になるまでループします。
構文は下記のとおりです
Do
{
繰り返し実行したい処理
}
While (条件式)

では sample3のように入力し、DoUntil.ps1 と名前を付けて保存してください。
このスクリプトは
$a を0で初期化し、Doの中で変数の値を表示(Write-Host)するようにしています。
変数の値を表示した後は、$aをインクリメントします。
最後の行の Loop で変数 $a が 5と等しいか(-eq)を判定し、5になるまでループを続けます。

sample3

$a = 0
Do
{
Write-Host $a
$a += 1
}
Until ( $a -eq 5 )
では、sample3を実行してみましょう。
実行結果はsample4のとおりです。
$a が 5に等しくなるまでループし、数値が表示されていることがわかります。

sample4

PS C:\Work2> ./DoUntil.ps1
0
1
2
3
4

01.関数を作成するには

PowerShellでの関数の基本構文は
function 関数名 {
関数本体
}

上記構文は、引数も戻り値もない場合です。
まずは、この構文を利用して "Hello boys and girls!!" と表示するだけの簡単な関数を作ってみます。
テキストエディタ(メモ帳など)を起動し sample1のように入力したら、Hello.ps1 という名前を付けて保存します。
1行目は関数がHelloという名前であることを示しています。
"{" ~ "}"までが関数本体を記述する場所になります。 ここではWrite-Outputコマンドレットを使用して、文字を表示するように記述しています。
一番最後の Hello ですが、ここで作成した関数 Hello を呼び出しています。 
この関数は引数がないので、関数名を書く = 関数をコールする となります。

sample1

function Hello {
Write-Output "Hello boys and girls!!"
}
Hello
では、実際に作成したスクリプトを実行してみます。
最初に、Set-Locationコマンドレットでスクリプトファイルを保存した場所へ移動します。(1)
次にスクリプトを実行します。 スクリプトを実行する場合は ./スクリプトファイル名 とします。 (2)
関数が実行され、結果として Hello boys and girls!! と表示されます。(3)

sample2

PS C:\Users\HIRO> Set-Location C:\Work ----(1)
PS C:\Work>
PS C:\Work> ./Hello.ps1 ----(2)
Hello boys and girls!! ----(3)

02.引数と戻り値のある関数を作成するには

引数と戻り値のある関数の基本構文は
function 関数名 (引数1, 引数2,...){
関数本体
[return 戻り値]
}

です。
戻り値がない場合は return 戻り値 は書く必要がありません。
簡単な例として、税込金額を求める関数 GetIncludingTax を作成してみます。
テキストエディタ(メモ帳など)を起動し sample1のように入力したら、IncludingTax.ps1 という名前を付けて保存します。
1行目は関数がIncludingTaxという名前であることを示しています。括弧の中の $price が引数で、税込前の金額を受け取るようにしています。
"{" ~ "}"までが関数本体を記述する場所になります。 $price に 1.05を掛けた値を return で返しています。
一番最後の GetIncudingTax 100 ですが、ここで作成した関数 GetIncudingTax を呼び出しています。 100 はIncludingTaxの引数に渡す値です。
PowerShellではカンマ演算子によって配列を表すため、C#などのように括弧を使用しての呼び出しを行いません。
引数のある関数の呼び出しは
関数名 引数1 引数2 ~
のように記述します。

sample1

function GetIncludingTax ($price) {
return $price * 1.05
}
GetIncludingTax 100
では、実際に作成したスクリプトを実行してみます。
最初に、Set-Locationコマンドレットでスクリプトファイルを保存した場所へ移動します。(1)
次にスクリプトを実行します。 スクリプトを実行する場合は ./スクリプトファイル名 とします。 (2)
関数が実行され、結果として 105 と表示されます。(3)

sample2

PS C:\Users\HIRO> Set-Location C:\Work ----(1)
PS C:\Work>
PS C:\Work> ./IncludingTax.ps1 ----(2)
105 ----(3)
paramキーワードを使用して、引数を受け取ることもできます。
sample1をparamキーワードを使用して書き換えたのが sample3です。

sample3

function GetIncludingTax {
param($price)
return $price * 1.05
}
GetIncludingTax 100

03.引数を省略可能にするには

PowerShellでは、引数が省略可能な関数を作成することができます。
省略可能な引数は
function 関数名 [(引数[=デフォルト値],..)] {
関数の本体
[return 戻り値]
}

で作成することができます。
引数を省略するということは、「省略された場合の値をあらかじめ設定しておく」という意味であることに注意してください。
引数と戻り値のある関数を作成するには で作成した GetIncludeTax 関数を省略可能に変更します。
引数が変更された場合は 100円の税込金額を計算するようにします。$price=100 として省略時の値を100としておく。
sample1のように入力したら、IncludingTax2.ps1 として保存します。

sample1

function GetIncludingTax ($price=100) {
return $price * 1.05
}
GetIncludingTax
GetIncludingTax 200
では、実際に作成したスクリプトを実行してみます。
最初に、Set-Locationコマンドレットでスクリプトファイルを保存した場所へ移動します。(1)
次にスクリプトを実行します。 スクリプトを実行する場合は ./スクリプトファイル名 とします。 (2)
最初に GetIncludingTax を引数なしで実行するので結果として105が返されます。(3)
次に GetIncludingTax 200 が実行されるので結果として205が返されます。(4)

sample2

PS C:\Users\HIRO> Set-Location C:\Work ----(1)
PS C:\Work>
PS C:\Work> ./IncludingTax2.ps1 ----(2)
105 ----(3)
210 ----(4)

04.引数を明示的に指定するには

PowerShellでは引数を明示的に指定することができます。
まずはBMIを計算する関数を作成してみましょう。
BMI(ボディマス指数)とは体重と身長の関係から人の肥満度を表す指数です)
BMIは 体重÷(身長(m)*身長(m)) で求めることができます。
ちなみにBMI 25以上が肥満、22が標準、18以下がやせ です

sample1

function BMI($weight, $height) {
return $weight / [math]::pow($height,2)
}
function BMIは引数を2つ持っているのですが、呼び出すときに
-引数名 値
と書くことで、明示的に値を渡すことができます。
sample2は、-weightに63(kg) -heightに1.63(m)を渡しています。

sample2

BMI -weight 63 -height 1.63
明示的に指定する場合は、引数の順番を入れ替えることが可能です。
sample3は -weightと-heightを入れ替えて呼び出しを行っています。
引数を入れ替えても、計算が正しく行われることを確認してください。

sample3

BMI -height 1.63 -weight 63

05.自動変数を使用して引数を受け取るには

PowerShellには$argsという自動変数があります。
自動変数を使用すると、関数の仮引数を明示的に宣言しなくても、値を受け取ることができます。
sample1ですが
関数 func は仮引数を明示的に宣言していません。
関数を呼び出すときに func 3 2 のようにすると、最初に指定した"3"がargs[0]に代入され、次に指定した"2"がargs[1]に入ります。
sample1のコードをメモ帳で入力して func.ps1 として保存します。

sample1

function func {
return $args[0] * $args[1]
}
func 3 2
sample1のコードを実行した結果は、下記のとおりです。
仮引数を明示的に宣言しなくても、自動変数に値が渡されて計算されていることが確認できます。

sample2

PS C:\Work> ./func.ps1
6

06.値渡しと参照渡し

PowerShellでは関数の引数に値渡しと参照渡しを使用することができます。
(注:ここでは値渡しと参照渡しの違いについては説明いたしません)
まずは値渡しの例です。(sample1)
まず test1を作成します。引数は$x1つとします。
test1という関数では受け取った$xを強制的に3に書き換えています。
最初に$xに1を代入します。(1)
関数 test1に$xを渡します。(2)
このとき関数内部では受け取った値を3に書き換えます
関数実行後の$xを確認します(3)
値渡しなので$xは(1)でセットした"1"を保持していいることがわかります。
しかし値渡しなので、関数を実行した後でも関数実行前の値を保持していることがわかります。

sample1

PS C:\Work> function test1 ($x)
>> {
>> $x = 3
>> }
>>
PS C:\Work2> $x = 1 ---(1)
PS C:\Work2> test1 $x ---(2)
PS C:\Work2> $x ---(3)
1
次に参照渡しの例です。(sample2)
sample1を参照渡し変更したtest2という関数を作成してみます。
参照渡しをするには、引数の前に[ref]を付けます。
また、関数内部では参照渡しで受け取った値は
$変数名.value
として使用しなければならないことに注意してください。
最初に$xに1を代入します。(1)
関数 test2に$xを渡します。(2)
このとき関数内部では受け取った値を3に書き換えます
関数実行後の$xを確認します(3)
参照渡しなので$xは(2)で書き換えられた"3"になっていることがわかります。
注意)参照渡しの関数の呼び出しは、([ref]$変数名)という形で引数を渡す必要があります。
しかし値渡しなので、関数を実行した後でも関数実行前の値を保持していることがわかります。

sample2

PS C:\Work> function test2 ([ref]$x)
>> {
>> $x.value = 3
>> }
>>
PS C:\Work2> $x = 1 ---(1)
PS C:\Work2> test2 ([ref]$x) ---(2)
PS C:\Work2> $x ---(3)
3

07.パイプライン引数

PowerShellでは、|で他のコマンドとパイプライン処理を行うことができます。
パイプラインから受け取った値は、$inputという自動変数に代入されます。
sample1では "Apple", "Orange", "Banana"の値をパイプラインで関数PrintStringへ渡しています。
foreachを使用して$inputへ代入された値を1つずつ取り出し、出力しています。

sample1

PS C:\Work> function PrintString {
>> foreach ( $a in $input )
>> {
>> Write-Host $a
>> }
>> }
>>
PS C:\Work2> "Apple", "Orange", "Banana" | PrintString
Apple
Orange
Banana
|を使用して関数を呼び出す場合は、begin, process, endキーワードを使用して、初期化から終了処理までを簡潔に書くことが可能です。
構文は
function 関数名 {
begin {最初に1度だけ実行される}
process {パイプラインで受けた値の数だけ繰り返される}
end {最後に1度だけ実行される}
}

です。
sample2をtest.ps1として保存して実行してみましょう。

sample2

function func1
{
begin { Write-Host "--Begin--"}
process { $input }
end { Write-Host "--End--" }
}
"Apple", "Orange", "Banana" | func1
実行結果はsample3のとおりです。
最初に --Begin-- という文字列が出力されます。(1)
次にパイプラインで受け取った値の数だけ process ブロックに書かれた処理を実行します。(2)
最後に --End-- という文字列を出力します。(3)

sample3

PS C:\Work2> ./test.ps1
--Begin--
Apple
Orange
Banana
--End--

08.フィルタ

フィルタ(filter)は関数に似ていますが、オブジェクトをフィルタするのに用います。
sample1は Get-ChildItemの結果をパイプラインで渡し、拡張子が*.txtのものをフィルタリングして表示しています。
この記述は、長いため何度も繰り返し記述するのは効率的ではありません。

sample1

PS C:\Work2> Get-ChildItem | where { $_.Extension -like "*.txt"}
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\Work2
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2007/12/04 23:14 20 a.txt
では、拡張子が *.txt のファイルを取り出すフィルタを作成してみましょう。
sample2のように入力して、TextFile.ps1 としてカレントフォルダへ保存します。

sample2

filter TextFile
{
if ( $_.Extension -like "*.txt" )
{
return $_
}
}
次に、. .\test.ps1[Enter]と入力し、作成したスクリプトを現在のスコープへ読み込みます。
Get-ChildItem | TextFile
とすると、作成したTextFileフィルタが働き、拡張子が *.txt のファイルが出力されます。

sample3

PS C:\Work2> . .\test.ps1
PS C:\Work2> Get-ChildItem | TextFile
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\Work2
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2007/12/04 23:14 20 a.txt

01.単一引用符と二重引用符

PowerShellで文字列を使用する場合は引用符で囲む必要があります。
使用できる引用符は2種類あり、単一引用符(')、二重引用符(")があります。
使用する引用符によって、囲まれた文字列の扱われ方が異なるので注意が必要です。
二重引用符の中で$記号で始まる変数が含まれていると、変数名が変数の値に置き換えられます。
sample1を見ると、二重引用符で囲まれた「$a」が、変数の値に置き換えられていることがわかります。

sample1

PS C:\Users\HIRO> $a = "test"
PS C:\Users\HIRO> Write-Host "$a"
test
sample1の二重引用符を単一引用符に置き換えてみたのが sample2 です。
sample2を見ると、単一引用符で囲まれた「$a」は、変数の値に置き換えられずに "$a" と表示されています。
このように単一引用符で囲まれた中にある変数は、変数の値に置き換は行われません。

sample2

PS C:\Users\HIRO> $a = "test"
PS C:\Users\HIRO> Write-Host '$a'
$a
二重引用符の中で$記号で始まる変数が含まれていても、変数名が変数の値に置き換えられないようにするにはアクサングラーブ文字 (`) を使用します。変数の直前にアクサングラーブ文字 (`)を使用すると、二重引用符の中でも変数が値に置き換えられることはありません。
sample3がその例です。

sample3

PS C:\Users\HIRO> $a = "test"
PS C:\Users\HIRO> Write-Host "`$a"
$a
単一引用符の中で二重引用符を使用することもできます。
この場合は、二重引用符を文字として出力することができます。(sample4参照)

sample4

PS C:\Users\HIRO> Write-Host 'Hello "HIRO"'
Hello "HIRO"
単一引用符や二重引用符を文字として扱うには、アクサングラーブ文字を使用します。

sample5

PS C:\Work> "HIRO`'s.NET"
HIRO's.NET
PS C:\Work> "`"HIRO`'s.NET`" is cool."
"HIRO's.NET" is cool.

02.アクサン グラーブ (`) 文字

PowerShellにおいてアクサン グラーブ (`) 文字は特別な意味を持っています。
Windows PowerShell では、次の特殊文字が認識されます。
`' 単一引用符
`" 二重引用符
`0 Null
`a 警告
`b バックスペース
`f 用紙送り
`n 新しい行
`r キャリッジリターン
`t 水平タブ
`v 垂直タブ

03.複数行にわたる文字列を使用するには

複数行にわたる文字列は「ヒアストリング」と呼ばれています。
ヒアストリングは @" から "@ で囲むか @' から'@で囲みます。

sample1

PS C:\Work> $a = @"
>> HIRO`'s.NET のURLは以下のとおりです。
>> http://hiro.wankuma.com/
>> "@
>>
PS C:\Work> $a
HIRO's.NET のURLは以下のとおりです。
http://hiro.wankuma.com/
改行コード(`rと`n)を使用して、複数行にわたる文字列を作成することもできます。

sample2

PS C:\Work2> $a="HIRO`'s.NET のURLは以下のとおりです。`r`n http://hiro.wankuma.com/"
PS C:\Work2> $a
HIRO's.NET のURLは以下のとおりです。
http://hiro.wankuma.com/

04.文字列を連結するには

配列に格納された文字列を結合することもできます。
この場合、System.String クラスの Join メソッドを使用します。
sample2 では
$a に "Power"と"Shell"の2つの文字列を代入しています。
次にJoinメソッドで"Power"と"Shell"を結合します。
Joinメソッドの構文は
Join( 配列の各要素の間に挿入する文字 , 配列変数 )
です。
ここでは "-"で結合しています。
よって結合結果は "Power-Shell" となります。

sample1

PS C:\Work2> $a = "Power", "Shell"
PS C:\Work2> $b = [string]::Join("-", $a)
PS C:\Work2> $b
Power-Shell
文字列の連結を行うには、プラス記号(+)を使用します。

sample2

PS C:\Work> $a = "Power" + "Shell"
PS C:\Work> $a
PowerShell
+= 演算子による連結
+= 演算子は、指定した値を変数の値に加算するか、指定した値を既存の値に追加します(sample3)

sample3

PS C:\Work> $a = "HIRO-"
PS C:\Work> $a += "NET"
PS C:\Work> $a
HIRO-NET
*= 演算子による連結
*= 演算子は、演算子の右側に記述した値の文だけ文字列が繰り返されます。(sample4)

sample4

PS C:\Work> $a = "Hiro"
PS C:\Work> $a *= 3
PS C:\Work> $a
HiroHiroHiro

05.文字列を分割するには

文字列を分割するには split() メソッドを使用します。
splitメソッドは、区切り文字(列)で、文字列を分割し結果を一次元配列で返します。
split() メソッドの構文は下記のとおりです
split( 区切り文字 )
sample1 では "Sun.,Mon.,Tue.,Wed.,Thu.,Fri.,Sat." という文字列をカンマ(,)で分割しています。

sample1

PS C:\Work> $a = "Sun.,Mon.,Tue.,Wed.,Thu.,Fri.,Sat."
PS C:\Work> $a.split(",")
Sun.
Mon.
Tue.
Wed.
Thu.
Fri.
Sat.

06.指定した文字のANSI文字コードを取得するには

PowerShellで指定した文字のANSI文字コードを取得するには、指定した文字(char型)を取得して、バイト値に変換する必要があります。
[byte][char]" ANSI文字コードを取得したい文字 "
と入力することで、ANSI文字コードを取得することができます。

sample1

PS C:\Work> $a = [byte][char]"a"
PS C:\Work> $a
97
ここからは sample1 についての説明です。
通常、 $a = "文字"と書くと、$aはString型となります。(sample2)

sample2

PS C:\Work> $a = "a"
PS C:\Work> $a.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
ANSIコードはバイト値として取得する必要がありますが、String型を直接バイト値に変換することはできません。
そこで Char型にキャストをしてから、バイト値に変換(キャスト)する必要があります。
Char型にキャストするには、キャストしたい値の前に[char]を付けます。
キャストした値の型を GetType() メソッドで調べてみると、Charになっているのを確認することができます。(sample3)

sample3

PS C:\Work> $a = [char]"a"
PS C:\Work> $a.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Char System.ValueType
Byte型にキャストするには、同様にして[byte]を付加します。
GetType() メソッドで調べるとByteになっているのがわかります。(sample4)
このようにして、調べたい文字を Char型にキャスト → Byte型にキャストすることでANSIコードを取得することができます。

sample4

PS C:\Work> $a = [byte][char]"a"
PS C:\Work> $a.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Byte System.ValueType

07.ANSI文字コードに関連付けられた文字を取得するには

PowerShellで指定したANSI文字コードに関連付けられた文字を取得するには、指定したANSI文字コードをChar型に変換します。
[char] ANSI文字コード
と入力することで、ANSI文字コードに関連付けられた文字を取得することができます。

sample1

PS C:\Work> $a = [char]97
PS C:\Work> $a
a

08.文字列の文字数をカウントするには

文字列の文字数をカウントするには、Lengthプロパティを使用します。
Lengthプロパティは
$変数名.Length

"文字列" .Length
のようにして使用します。

sample1

PS C:\Work> $a = "abcdefg"
PS C:\Work> $a.Length
7
PS C:\Work> "abcdefg".Length
7

09.文字列のバイト数をカウントするには

文字列のバイト数をカウントするには、Encoding.GetByteCount メソッドを使用します。
sample1では文字列 "あいうえお" のバイト数を取得しています。

sample1

PS C:\Work> [System.Text.Encoding]::GetEncoding("Shift_Jis").GetByteCount("あいうえお")
10

10.英小文字/英大文字を相互変換するには

英小文字を英大文字に変換するには ToUpper() メソッドを使用します。
$変数名.ToUpper()

"文字列" .ToUpper()
のようにして使用します。

sample1

PS C:\Work> "abc".ToUpper()
ABC
英大文字を英小文字に変換するには ToLower() メソッドを使用します。

$変数名.ToLower()


"文字列" .ToLower()
のようにして使用します。

sample2

PS C:\Work> "ABC".ToLower()
abc

11.ひらがな/カタカナを相互変換するには

本 Tips は TechNet( http://forums.microsoft.com/TechNet-JA/ShowPost.aspx?PostID=2109367&SiteID=36 )を参考にしました。
PowerShellでひらがな/カタカナを相互変換するには、Mirosoft.VisualBasic名前空間にあるstrConv関数を使用します。
最初に Microsoft.VisualBasic名前空間を使用できるようにsample1のように入力して下準備を行います。

sample1

PS C:\Work> [reflection.assembly]::LoadWithPartialName("Microsoft.VisualBasic")
GAC Version Location
--- ------- --------
True v2.0.50727 C:\WINDOWS\assembly\GAC_MSIL\Microsoft.VisualBasic\8.0.0.0__...
次に StrConv関数の第2引数に渡すパラメータをあらかじめ変数に入れておきます。
(関数呼び出し時に直接記述することもできますが、長くて見ずらいことを解消するため変数にセットしておきます)
$vbHiragana へ VbStrConv.Hiragana を
$vbKatakana へ VbStrConv.Katakana を
セットします。(sample2)

sample2

PS C:\Work> $vbHiragana = [Microsoft.VisualBasic.VbStrConv]::Hiragana
PS C:\Work> $vbKatakana = [Microsoft.VisualBasic.VbStrConv]::Katakana
ひらがなをカタカナへ変換するには、sample3のようにします。

sample3

PS C:\Work> [Microsoft.VisualBasic.Strings]::StrConv("あいうえお", $vbKatakana)
アイウエオ
カタカナをひらがなへ変換するには、sample4のようにします。

sample4

PS C:\Work> [Microsoft.VisualBasic.Strings]::StrConv("アイウエオ", $vbHiragana)
あいうえお

12.文字列を検索し最初に見つかった位置を取得する

文字列を検索し最初に見つかった位置を取得するには、IndexOfメソッドを使用します。IndexOfメソッドは見つかった位置を0番目から数えて返します。
sample1では文字列から直接"c"の文字位置を取得しています。

sample1

PS C:\Users\HIRO> $a = "abcdef"
PS C:\Users\HIRO> $a.IndexOf("c")
2
sample2ではString型の変数から"c"の文字位置を取得しています。

sample2

PS C:\Users\HIRO> $a = "abcdef"
PS C:\Users\HIRO> $a.IndexOf("c")
2
IndexOfメソッドは大文字/小文字を区別するので、sample3のように"abcdef"から"C"を探そうとした場合には見つからないので-1を返します。

sample3

PS C:\Users\HIRO> $a = "abcdef"
PS C:\Users\HIRO> $a.IndexOf("C")
-1

13.文字列を検索し最後に見つかった位置を取得する

文字列を検索し最後に見つかった位置を取得するにはStringクラスのLastIndexOfメソッドを使用します。LastIndexOfメソッドは見つかった位置を0番目から数えて返します。見つからなかった場合は-1を返します。
sample1では、"abcdefabcdef"の中から、最後に現れる("d")の位置を取得しています。
先頭(0番目)から数えて、9番目が最後に現れる"d"の位置です。

sample1

PS C:\Users\HIRO> $a = "abcdefabcdef"
PS C:\Users\HIRO> $a.LastIndexOf("d")
9
LastIndexOfメソッドは、sample2のように文字列から直接"d"の値を取得しています。

sample2

PS C:\Users\HIRO> "abcdefabcdef".LastIndexOf("d")
9
LastIndexOfメソッドは、大文字/小文字を区別するため、sample3のように入力した場合は"D"がないため、-1を返します。

sample3

PS C:\Users\HIROKI> $a = "abcdefabcdef"
PS C:\Users\HIROKI> $a.LastIndexOf("D")
-1

14.指定した文字列が含まれているかをチェックするには

指定した文字列が含まれているかを確認するには、いくつか方法があります。
1つ目はIndexOfメソッドを使用する方法です。
IndexOfメソッドは、指定した文字(列)が見つかった場合は0以上の数を返します。また見つからなかった場合は-1を返しますので、このことを利用すれば、指定した文字列が含まれているかどうかを判定することができます。
sample1では、"abcdef"の中に"cd"を含んでいるかをチェックしています。
"cd"は2文字目にあるので結果として2が返ります。
-1ではなかったので、「文字が含まれている」と判定することができます。

sample1

PS C:\Users\HIRO> $a = "abcdef"
PS C:\Users\HIRO> $a.IndexOf("cd")
2
次に、Containsメソッドです。このメソッドは、指定した文字(列)が含まれている場合はTrueを返します。
sample2では、"abcdefg"に中に"cd"が含まれているかを contains メソッドで確認しています。
文字列"cd"は含まれているので、Trueを返します。

sample2

PS C:\Users\HIRO> $a = "abcdefg"
PS C:\Users\HIRO> $a.Contains("cd")
True

15.文字列を数値に変換するには

文字列は、文字列を代入した変数または文字列自身の先頭に[int],[double],[single]のいずれかを付けることで数値に変換することができます。
[int] 32 ビット整数
[double] 倍精度浮動小数点数
[single] 単精度浮動小数点数

sample1

PS C:\Users\HIRO> $a = "3.14"
PS C:\Users\HIRO> $a = [int]$a
PS C:\Users\HIRO> $a.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Int32 System.ValueType

16.桁区切り文字を含む文字列を数値に変換するには

桁区切り文字を含む文字列を数値に変換するには、Parseメソッドを使用します。第2引数に[System.Globalization.NumberStyles]::AllowThousandsを指定します。"123,456"のような文字列でも正しく123456と変換することが出来ます。

sample1

PS C:\Users\HIRO> [int]::Parse("123,456",[System.Globalization.NumberStyles]::AllowThousands)
123456

17.文字列が数値として有効かどうかを判断して数値に変換するには

文字列が数値として有効かどうかを判断して数値に変換するには、各数値型で実装されているTryParseメソッドを使用します。TryParseメソッドは変換が成功した場合にはTrueを返します。また、第2引数で、変換結果を参照することが出来ます。
構文は下記の通りです。
bool TryParse( "数値に変換する文字列" , [ref] 変数 )
sample1では"12345"が int型へ変換可能かをTryParseで確認しています。(1)
"12345"はint型へ変換可能なのでTrueを返しています。(2)
(3)で変換結果を確認しています。
変換が正常に行われているので、結果として 12345 を返しています。(4)

sample1

PS C:\Users\HIRO> [int]::TryParse("12345",[ref]$a) ---(1)
True ---(2)
PS C:\Users\HIRO> $a ---(3)
12345 ---(4)
sample2は double での例です。

sample2

PS C:\Users\HIRO> [double]::TryParse("123.456", [ref]$a)
True
PS C:\Users\HIRO> $a
123.456

18.数値を16進数文字列に変換するには

数値を16進数文字列に変換するにはToStringメソッドを使用します。ToStringメソッドの引数に"X"を指定すると大文字に変換表示、"x"を指定すると小文字に変換、"X2"を指定すると大文字2桁で変換します。

sample1

PS C:\Users\HIROKI> $a = 12
PS C:\Users\HIROKI> $a.ToString("X")
C
PS C:\Users\HIROKI> $a.ToString("X2")
0C
PS C:\Users\HIROKI> $a.ToString("X4")
000C
PS C:\Users\HIROKI> $a.ToString("x")
c
PS C:\Users\HIROKI> $a.ToString("x2")
0c

19.16進数文字列を数値に変換するには

16進数文字列を数値に変換するにはConvertクラスを使用します。
第2引数に基数の16を指定することで16進数文字列からint型へ変換しています。

sample1

PS C:\Users\HIRO> [System.Convert]::ToInt32("1F",16)
31
PS C:\Users\HIRO> [System.Convert]::ToInt32("0x1F",16)
31

20.数値を2進数文字列に変換するには

数値を2進数文字列に変換するにはConverクラスのToStringメソッドを使用します。ToStringメソッドの第2引数に基数の2を指定することで2進数に変換することが出来ます。

sample1

PS C:\Users\HIRO> [System.Convert]::ToString(10, 2)
1010
PS C:\Users\HIRO> [System.Convert]::ToString(15, 2)
1111

21.2進数文字列を数値に変換するには

2進数文字列を数値に変換するにはConvertクラスを使用します。
第2引数に基数の2を指定することで2進数からint型へ変換しています。

sample1

PS C:\Users\HIRO> [System.Convert]::ToInt32("1010", 2)
10
PS C:\Users\HIRO> [System.Convert]::ToInt32("1111", 2)
15

22.文字列を削除するには

文字列を削除するにはStringクラスのRemoveメソッドを使用します。第1引数に削除開始位置を、第2引数には削除する文字数を指定します。

sample1

PS C:\Users\HIRO> $a = "ABCDEFG"
PS C:\Users\HIRO> $a.Remove(3, 2)
ABCFG

23.文字列を置換するには

文字列を置換するにはStringクラスのReplaceメソッドを使用します。第1引数に置換対象文字列を、第2引数には置換後の文字列を指定します。
sample1では "ABCDEFGHI"の"DEF"を"---"に置換しています。

sample1

PS C:\Users\HIRO> $a = "ABCDEFGHI"
PS C:\Users\HIRO> $a.Replace("DEF", "---")
ABC---GHI

24.文字列を挿入するには

文字列を挿入するには、StringクラスのInsertメソッドを使用します。第1引数に挿入位置を、第2引数に挿入文字列を指定します。
sample1では、"ABCGHI"に"DEF"を挿入しています。

sample1

PS C:\Users\HIRO> $a = "ABCGHI"
PS C:\Users\HIRO> $a.Insert(3, "DEF")
ABCDEFGHI

25.指定した文字列で始まっているかチェックするには

指定した文字列で始まるかをチェックするにはStartsWithメソッドを使用します。指定した文字列で始まっている場合はTrueを返します。StartsWithは大文字/小文字を識別することに注意してください。

sample1

PS C:\Users\HIRO> $a = "Hello VB.NET"
PS C:\Users\HIRO> $a.StartsWith("Hello")
True
PS C:\Users\HIRO> $a.StartsWith("HELLO")
False

26.指定した文字列で終了しているかチェックするには

指定した文字列で終了しているかをチェックするにはEndsWithメソッドを使用します。指定した文字列で終了している場合はTrueを返します。EndsWithメソッドは大文字/小文字を識別することに注意してください。

sample1

PS C:\Users\HIRO> $a = "Hello VB.NET"
PS C:\Users\HIRO> $a.EndsWith("NET")
True
PS C:\Users\HIRO> $a.EndsWith("net")
False

27.文字列の前後の空白を削除するには

文字列の空白の前後の空白を削除するには、Trimメソッド, TrimStartメソッド, TrimEndメソッドのいずれかを使用します。
sample1はTrimメソッドの例です。
Trimメソッドは文字列の前後の空白を削除します。

sample1

PS C:\Users\HIRO> $a = " HIRO "
PS C:\Users\HIRO> "-" + $a.Trim() + "-"
-HIRO-
sample2はTrimStartメソッドの例です。
TrimStartメソッドは文字列の前の空白を削除します。

sample2

PS C:\Users\HIRO> $a = " 'HIRO' "
PS C:\Users\HIRO> "-" + $a.TrimStart() + "-"
-'HIRO' -
sample3はTrimEndメソッドの例です。
TrimEndメソッドは文字列の前の空白を削除します。

sample3

PS C:\Users\HIRO> $a = " 'HIRO' "
PS C:\Users\HIRO> "-" + $a.TrimEnd() + "-"
- 'HIRO'-

28.文字を右寄せ/左寄せするには

文字列を右寄せするには、PadLeftメソッド、左寄せするにはPadRightメソッドを使用します。
引数で指定した文字数になるまでスペースを追加します。スペースではなく指定した文字で埋めたい場合は第2引数にその文字を指定します。
sample1の(1)は文字列"ABC"を右寄せし、空白を含めて6文字になるようにしています。
sample1の(2)は文字列"ABC"を左寄せし、空白を含めて6文字になるようにしています。
((2)は右側に3文字の空白が追加されたことが確かめられるよう - を末尾に追加しています)

sample1

PS C:\Users\HIRO> $a = "ABC" ---(1)
PS C:\Users\HIRO> $a.PadLeft(6)
ABC
PS C:\Users\HIRO> $a = "ABC" ---(2)
PS C:\Users\HIRO> $a.PadRight(6) + "-"
ABC -
sample2の(1)は文字列"ABC"を右寄せし、Xを含めて6文字になるようにしています。
sample2の(2)は文字列"ABC"を左寄せし、Xを含めて6文字になるようにしています。

sample2

PS C:\Users\HIRO> $a = "ABC" ---(1)
PS C:\Users\HIRO> $a.PadLeft(6,"X")
XXXABC
PS C:\Users\HIRO> $a = "ABC" ---(2)
PS C:\Users\HIRO> $a.PadRight(6,"X")
ABCXXX

01.ファイルの一覧を表示する Part1

指定したディレクトリのファイル一覧を表示するにはGet-ChildItemコマンドレットを使用します。
基本構文は
Get-ChildItem ディレクトリパス
ディレクトリパスは省略することが可能です。
省略した場合には、カレントフォルダのファイル一覧が表示されます。
Get-ChildItemの代わりに、gci, dir, ls と入力しても同じ結果が得られます。
これらはGet-ChildItemのエイリアスとして定義されています。
sample1ではフォルダ名を省略して Get-ChildItem コマンドレットを実行しているので、カレントフォルダの C:\Work にあるファイル一覧を表示しています。

sample1

PS C:\Work> Get-ChildItem
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\Work
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2007/12/11 22:05 FolderA
d---- 2007/12/11 22:05 FolderB
-a--- 2007/11/17 23:25 37 GetChildItem.ps1
-a--- 2007/11/17 23:58 37 GetRegSoft.ps1
-a--- 2006/11/03 21:13 9211 styles.css
-a--- 2007/05/08 23:00 32925 style_screen.css
-a--- 2007/11/04 23:15 6257 Table.css
-a--- 2007/12/10 23:26 34282 test.csv
-a--- 2007/10/31 23:44 1655296 Tips20071031.bak
次に、拡張子が css のファイルを取得してみます。
Get-ChildItemではワイルドカードを使用することが可能です。
sample2では、カレントディレクトリの拡張子がcssのファイルの一覧を取得しています。

sample2

PS C:\Work> Get-ChildItem *.css
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\Work
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2006/11/03 21:13 9211 styles.css
-a--- 2007/05/08 23:00 32925 style_screen.css
-a--- 2007/11/04 23:15 6257 Table.css
sample3 では、カレントディレクトリとそのサブディレクトリ下にある *.css のファイル一覧を取得します。
Get-ChildItemコマンドレットの右にあるドット(.)がカレントディレクトリを意味しています。カレントディレクトリ以外のパスを指定することも可能です。
-Include パラメータは *.css などのパス要素またはパターンを指定します。
-recurse パラメータは指定された場所にある項目と、その場所のすべての子項目を取得します。

sample3

PS C:\Work> Get-ChildItem . -Include *.css -recurse
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\Work\FolderA
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2007/12/11 22:10 0 style1.css
-a--- 2007/12/11 22:10 0 style2.css
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\Work\FolderB
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2007/12/11 22:10 0 style3.css
-a--- 2007/12/11 22:10 0 style4.css
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\Work
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2006/11/03 21:13 9211 styles.css
-a--- 2007/05/08 23:00 32925 style_screen.css
-a--- 2007/11/04 23:15 6257 Table.css
sample4 では 2つのフォルダから *.ps1 のファイル一覧を取得しています。
複数のフォルダから取得する場合は -path パラメータを使用します。

sample4

PS C:\Work> Get-ChildItem -path C:\Work2\*.ps1, C:\Work3\*.ps1
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\Work2
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2007/12/04 16:46 109 BMI.ps1
-a--- 2007/12/04 16:52 78 BMI2.ps1
-a--- 2007/12/06 10:10 66 DoLoop.ps1
-a--- 2007/12/06 9:57 66 DoWhile.ps1
-a--- 2007/12/04 17:14 41 func.ps1
-a--- 2007/12/03 16:23 85 Hello.ps1
-a--- 2007/12/03 17:26 118 IncludingTax.ps1
-a--- 2007/12/04 17:14 41 Triangle.ps1
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\Work3
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2007/12/12 9:57 0 Test.ps1

02.ファイルの一覧を表示する Part2

sample1 では -excludeパラメータを使用して、指定した拡張子以外(ここでは*.ps1を除外)のファイル一覧を取得しています。

sample1

PS C:\Work> Get-ChildItem -exclude *.ps1
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\Work
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2007/12/11 22:10 FolderA
d---- 2007/12/11 22:11 FolderB
-a--- 2006/11/03 21:13 9211 styles.css
-a--- 2007/05/08 23:00 32925 style_screen.css
-a--- 2007/11/04 23:15 6257 Table.css
-a--- 2007/12/10 23:26 34282 test.csv
-a--- 2007/10/31 23:44 1655296 Tips20071031.bak
sample2 では -excludeパラメータを使用して、複数の拡張子を場外して(ここでは*.ps1, *.cssを除外)ファイル一覧を取得しています。複数の拡張子を除外するには、-excludeパラメータのあとに拡張子をカンマで区切って指定します。

sample2

PS C:\Work> Get-ChildItem -exclude *.ps1, *.css
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\Work
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2007/12/11 22:10 FolderA
d---- 2007/12/11 22:11 FolderB
-a--- 2007/12/10 23:26 34282 test.csv
-a--- 2007/10/31 23:44 1655296 Tips20071031.bak
sample3ではパイプ処理を行って、Nameプロパティ(ファイル名)とLength(サイズ)プロパティのみを取得しています。

sample3

PS C:\Work> Get-ChildItem *.* | Select-Object Name, Length
Name Length
---- ------
GetChildItem.ps1 37
GetRegSoft.ps1   37
styles.css 9211
style_screen.css 32925
Table.css 6257
test.csv 34282
Tips20071031.bak 1655296
sample4は拡張子が*.cssのファイル一覧を取得し、変数 $a に代入する例です。
$a.Lengthとすることで、取得したファイル数を確認することができます。

sample4

PS C:\Work> $a = Get-ChildItem *.css
PS C:\Work> $a
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\Work
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2006/11/03 21:13 9211 styles.css
-a--- 2007/05/08 23:00 32925 style_screen.css
-a--- 2007/11/04 23:15 6257 Table.css
PS C:\Work> $a.Length
3

03.テキストファイルを作成する Part1

テキストファイルを作成するには、リダイレクション演算子を使用します。
sample1では、文字列"abc"をカレントディレクトリに sample1.txt というファイル名で作成します。

sample1

PS C:\Work> "abc" > sample1.txt
ヒア文字列を使用すれば、複数行にわたる文字列のテキストファイルを作成することも可能です。
sample2では、HIRO_URL.txtに複数行の文字列を書き込んでいます。

sample2

PS C:\Work> $a = @"
>> HIRO`'s.NET のURLは以下のとおりです。
>> http://hiro.wankuma.com/
>> "@ > HIRO_URL.txt
>>

04.テキストファイルを作成する Part2

PowerShellでは Out-Fileコマンドレットを使用して、テキストファイルを作成することができます。
リダイレクション演算子(>)を使用するよりも、より細かな操作を行うことが可能です。
基本構文
"ファイルに書き込む文字列" | Out-File "出力ファイルパス"
sample1では"abc"という文字列が書かれた Test.txt ファイルを作成します。

sample1

PS C:\Work> "abc" | Out-File Test.txt
次に文字エンコードの種類を指定してファイルを作成する例です。
文字エンコードを指定するには、-encoding パラメータを使用します。
-encodingパラメータには、Unicode、UTF7、UTF8、UTF32、ASCII、BigEndianUnicode、Default、および OEM です。-encoding を省略した場合は Unicode となります。
sample2では、文字コードの種類にUTF8を指定してテキストファイルを作成しています。

sample2

PS C:\Work> "あいうえお" | Out-File sample.txt -encoding UTF8
次は、ファイルの末尾に追加する例です。
ファイルの末尾に、指定したテキストを追加するには -append パラメータを使用します。
sample3 では文字コードの種類にUTF8を指定して、"あいうえお"と書かれたファイル(sample.txt)を作成します。(1)
Get-Content コマンドレットでファイルに書き込まれた内容を確認します。(2)
次に、sample.txt に"かきくけこ"というテキストをファイルの末尾に追加します。(3)
ファイルの内容を確認してみると、末尾に"かきくけこ"が追加されたことを確認することができます。(4)

sample3

PS C:\Work> "あいうえお" | Out-File sample.txt -encoding UTF8 (1)
PS C:\Work> Get-Content sample.txt (2)
あいうえお
PS C:\Work> "かきくけこ" | Out-File sample.txt -encoding UTF8 -append (3)
PS C:\Work> Get-Content sample.txt (4)
あいうえお
かきくけこ

05.テキストファイルを作成する Part3

sample1 はファイルが既に存在する場合は、上書きできないようにする例です。
上書きできないようにするには、 -NoClobberパラメータ を使用します。
すでにファイルが存在する場合には、sample1のようにエラーが返されます。

sample1

PS C:\Work> "ABCDEF" | Out-File sample.txt -NoClobber

Out-File : ファイル C:\Work\sample.txt は既に存在しますが、NoClobber が指定されました。
発生場所 行:1 文字:20
+ "ABCDEF" | Out-File <<<< sample.txt -NoClobber

sample2は出力行の文字数を制限する例です。
1行に出力可能な文字数を制限するには、 -widthパラメータ を使用します。
sample2では Get-Processの取得結果を、1行に30文字という制限をかけてProcess.txt に書き込んでいます。(1)
次にGet-Contentコマンドレットで書き込まれた内容を確認しています。(2)
1行に30文字という制限をかけたため Get-Process の取得結果であるWS(K),VM(M),CPU(s),Id ProcessName が書き込まれなかったため、警告メッセージも書き込まれています。

sample2

PS C:\Work> Get-Process | Out-File Process.txt -width 30 (1)
PS C:\Work> Get-Content Process.txt (2)
警告: 4 個の列が表示に収まらないため、削除されました。
Handles NPM(K) PM(K) WS(K)
------- ------ ----- -----
104 5 1316 640
66 3 1472 488
76 3 2084 604
256 38 5724 968
317 7 4436 320
192 5 4160 476
117 5 3248 3232
265 11 13588 15864
791 7 8836 10628
215 13 2812 3920

06.ファイルをコピーする

ファイルをコピーするには Copy-Item コマンドレットを使用します。
基本構文は
Copy-Item コピー元ファイルパス コピー先ファイルパス
です。
sample1では C:\Work\A.txt を C:\Work2にコピーします。

sample1

PS C:\Work> Copy-Item C:\Work\A.txt C:\Work2\A.txt
ファイル名を変えてをコピーするには sample2のようにします。
sample2では、C:\Work\A.txt をC:\Work2 に B.txtという名前にしてコピーを行います。

sample2

PS C:\Work> Copy-Item C:\Work\A.txt C:\Work2\B.txt
ファイルコピー時に確認メッセージを表示させるには -confirm パラメータ を使用します。

sample3

PS C:\Work> Copy-Item C:\Work\A.txt C:\Work2\A.txt -Confirm
確認
この操作を実行しますか?
対象 "項目: C:\Work\A.txt コピー先: C:\Work2\A.txt" に対して操作 "ファイルのコピー" を実行しています。
[Y] はい(Y) [A] すべて続行(A) [N] いいえ(N) [L] すべて無視(L) [S] 中断(S) [?] ヘルプ (既定値は "Y"): N
ワイルドカードを使用して、複数ファイルをコピーすることもできます。(sample4)
sample4では C:\Workに存在するテキストファイル(*.txt)を C:\Work2 にコピーします。
複数のファイルをコピーする場合は、第2引数にコピー先フォルダのパスを指定してください。

sample4

PS C:\Work> Copy-Item C:\Work\*.txt C:\Work2

07.ファイルを移動する

ワイルドカードを使用して、複数ファイルを移動することもできます。(sample4)
sample4では C:\Workに存在するテキストファイル(*.txt)を C:\Work2 に移動します。
複数のファイルを移動する場合は、移動先のパスにフォルダを指定してください。

sample1

PS C:\Work> Move-Item C:\Work\*.txt C:\Work2
ファイルを移動するには、Move-Item コマンドレットを使用します。
基本構文は
Move-Item 移動元パス 移動先パス
です。
移動先にすでにファイルが存在する場合は、エラーとなることに注意してください。

sample2

PS C:\Work> Move-Item C:\Work\A.txt C:\Work2\A.txt
移動先にすでにファイルがある場合でも、移動元のファイルを移動させるには -force パラメータ を使用します。
構文は下記のとおりです。
Move-Item 移動元パス 移動先パス -force
この場合は、既に存在するファイルに上書きするような形で移動が行われます。
元の情報を失っては困る場合は -force パラメータを使用しないようにしてください。

sample3

PS C:\Work> Move-Item C:\Work\A.txt C:\Work2\A.txt -force
ファイル移動時に確認メッセージを表示させるには -confirm パラメータ を使用します。

sample4

PS C:\Work> Move-Item C:\Work\A.txt C:\Work2\A.txt -confirm
確認
この操作を実行しますか?
対象 "項目: C:\Work\A.txt 移動先: C:\Work2\A.txt" に対して操作 "ファイルの移動" を実行しています。
[Y] はい(Y) [A] すべて続行(A) [N] いいえ(N) [L] すべて無視(L) [S] 中断(S) [?] ヘルプ (既定値は "Y"):

08.ファイルを削除する

ファイルを削除するには Remove-Item コマンドレットを使用します。
基本構文は
Remove-Item 削除するファイル
です。
sample1では C:\Work にある A.txt を削除します。

sample1

PS C:\Work> Remove-Item C:\Work\A.txt
ワイルドカードを使用して、複数のファイルを削除することも可能です。
sample2では C:\Work にある *.txt ファイルを削除します。

sample2

PS C:\Work> Remove-Item *.txt
ファイルを削除するときに確認メッセージを表示するには、 -confirm パラメータを使用します。(sample3)
複数のファイルを削除する場合は、1ファイルずつ確認が行われます。
確認メッセージの「[A]すべて続行(A)」を選択すれば、一気に削除することができます。

sample3

PS C:\Work3> Remove-Item *.txt -Confirm
確認
この操作を実行しますか?
対象 "C:\Work3\Process.txt" に対して操作 "ファイルの削除" を実行しています。
[Y] はい(Y) [A] すべて続行(A) [N] いいえ(N) [L] すべて無視(L) [S] 中断(S) [?] ヘルプ (既定値は "Y"): Y
次に特定のファイルを除いて削除する方法を紹介します。
特定のファイルを除外するには -exclude パラメータを使用します。
sample4 では file*.txt と folder*.txt のファイルがそれぞれ3つずつあります。(1)
-excludeパラメータを使用して、ファイル名が folder で始まるファイルを除いて削除します。(2)
結果を見てみると、folder*.txt のファイルを残して削除がされていることがわかります。

sample4

PS C:\Work3> Get-ChildItem ---(1)
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\Work3
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2007/12/13 15:46 14 file01.txt
-a--- 2007/12/13 15:46 14 file02.txt
-a--- 2007/12/13 15:46 14 file03.txt
-a--- 2007/12/13 15:46 14 folder01.txt
-a--- 2007/12/13 15:46 14 folder02.txt
-a--- 2007/12/13 15:46 14 folder03.txt
PS C:\Work3> Remove-Item *.txt -exclude folder*.txt ---(2)
PS C:\Work3> Get-ChildItem ---(3)
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\Work3
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2007/12/13 15:46 14 folder01.txt
-a--- 2007/12/13 15:46 14 folder02.txt
-a--- 2007/12/13 15:46 14 folder03.txt
次に、読み取り専用ファイルや隠しファイルを削除する方法を紹介します。
読み取り専用ファイルや隠しファイルを削除するには、 -force パラメータを使用します。
-forceパラメータを使用せずに削除しようとした場合には(1)のようにエラーが表示されます。
-forceパラメータを使用することで、削除ができます。(2)

sample5

PS C:\Work> Remove-Item Test.txt ---(1)
Remove-Item : 項目 C:\Work\Test.txt を削除できません: 操作を実行するために十分なアクセス許可がありません。
発生場所 行:1 文字:12
+ Remove-Item <<<< Test.txt
PS C:\Work3> Remove-Item Test.txt -force ---(2)

09.ファイルの存在を確認する

ファイルの存在を確認するには Test-Path コマンドレットを使用します。
Test-Pathコマンドレットは、指定したパスが存在する場合には TRUE を返します。

sample1

PS C:\Work> Test-Path C:\Work\Test.txt
True

10.ファイルの作成日時/更新日時を取得する

いくつか方法はあると思いますが、ここでは Get-ItemProperty コマンドレットを使用した方法を紹介します。
Get-ItemProperty は指定した項目のプロパティを取得するコマンドレットです。
基本構文は
Get-ItemProperty 項目
です。
項目にファイルパスを指定すると、そのファイルの情報を取得することができます。sample1

sample1

PS C:\Work> Get-ItemProperty Test.txt
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\Work
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2007/12/13 15:46 14 Test.txt
ファイル作成日時を取得するには CreationTimeプロパティ を使用します。
sample2のようにすることで、指定したファイルの作成日時を取得することができます。

sample2

PS C:\Work> $(Get-ItemProperty Test.txt).CreationTime
2007年8月28日 14:56:10
ファイル更新日時を取得するには LastWriteTimeプロパティ を使用します。
sample3のようにすることで、指定したファイルの更新日時を取得することができます。

sample3

PS C:\Work> $(Get-ItemProperty Test.txt).LastWriteTime
2007年12月13日 15:46:50

11.ファイルの作成日時/更新日時を設定する

sample2では、ファイルの更新日時を、現在の日時で設定しています。

sample1

PS C:\Work> Set-ItemProperty Test.txt -name LastWriteTime -value $(Get-Date)
いくつか方法はあると思いますが、ここでは Set-ItemProperty コマンドレットを使用した方法を紹介します。
Set-ItemProperty は指定した項目のプロパティを設定するコマンドレットです。
基本構文は
Set-ItemProperty 項目 -name プロパティ名 -value 設定する値
です。
sample1 は C:\Work にある Test.txt というファイルの作成日時を設定する例です。
パラメータ -name で CreationTimeプロパティを設定することを宣言しています。
パラメータ -value で設定する値を指定します。ここでは現在日時を設定しています。

sample2

PS C:\Work> Set-ItemProperty Test.txt -name CreationTime -value $(Get-Date)

12.ファイルの属性を取得する

ファイルの属性を取得するもっとも簡単な方法は、Get-ChildItemコマンドレットを使用することです。
Get-ChidItemコマンドレットを実行すると サンプル1のような結果が得られるのですが、一番左側のMode列がファイルの属性を表しています。
意味は下記の通りです
d ディレクトリ
a アーカイブ
r 読み取り専用
h 隠しファイル
s システムファイル

sample1

PS C:\Work> Get-ChildItem
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\Work
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2007/11/09 11:02 ACS001
d---- 2007/08/28 14:53 ACS002
-a--- 2007/06/22 14:28 720788 BioClient.zip
-a--- 2007/09/10 10:00 302 compile.sql
-a--- 2007/08/02 15:40 436 result.xml
次に System.IO.FileAttributes を利用してファイル属性を取得してみましょう。(sample2)
New-Objectコマンドレットを使用してSystem.IO.FileAttributes オブジェクトを作成します(1)
次にファイル属性を調べたいファイルを指定します。(2)
変数に属性がセットされているので内容を確認します。(3)(4)

sample2

PS C:\Work> $fileattr = New-Object System.IO.FileAttributes ---(1)
PS C:\Work> $fileattr = [System.IO.File]::GetAttributes("C:\Work\Test.txt") ---(2)
PS C:\Work> $fileattr ---(3)
Archive ---(4)
上記を踏まえて属性を取得表示する関数を作成してみました。 sample3

sample3

function global:Get-FileAttributes()
{
Param([String]$filepath)
$fileattr = New-Object System.IO.FileAttributes
$fileattr = [System.IO.File]::GetAttributes($filepath)
Write-Host $fileattr
}
使用方法は、sample4のように
Get-FileAttributes "属性を調べたいファイル"
です。
必要に応じて、各自変更してお使いください。

sample4

PS C:\Work> Get-FileAttributes C:\Work\Test2.txt
ReadOnly, Hidden, Archive

13.ファイルの属性を設定する

ファイルの属性を設定するには、Set-ItemProperty コマンドレットを使用します。
書式は
Set-ItemProperty -path "属性を設定するファイルのパス" -name Attributes -value "属性"
です。
指定できる属性には下記のようなものがあります
アーカイブ Archive
読み取り専用 Readonly
隠しファイル Hidden
システムファイル System
sample1では、"C:\Work\Test.txt"に対して隠し属性(Hidden)を付けています。

sample1

PS C:\Users\HIRO> Set-ItemProperty -path "C:\Work\Test.txt" -name Attributes -value "Hidden"
2つ以上の属性を一度に指定するには、sample2のようにカンマで区切って指定します。
sample2の場合は読み取り専用(Readonly)と隠し属性(Hidden)を一度に指定しています。
属性を設定したら、Get-ItemPropertyコマンドレットで確認してみてください。

sample2

PS C:\Work> Set-ItemProperty -path "C:\Work\Test.txt" -name Attributes -value "Readonly,Hidden"
PS C:\Work> Get-ItemProperty -path "C:\Work\Test.txt"
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\Work
Mode LastWriteTime Length Name
---- ------------- ------ ----
--rh- 2007/12/17 16:20 14 Test.txt

14.ファイルのサイズを取得する

ファイルのサイズを取得するには Get-ChildItem コマンドレットを使用します。
sample1のようにして、Lengthプロパティの値だけを取得することで、ファイルサイズを取得できます。
このときのファイルサイズの単位はバイトです。

sample1

PS C:\Work> $(Get-ChildItem "HIRO1.mdf").Length
2293760
PowerShell ではバイト計算を行うことができます。
下記のようなものがあります。
KB キロバイト
MB メガバイト
GB ギガバイト
コマンドウィンドウに 1KB と入力し[Enter]を押してみてください。(1)
1024と表示されるはずです。これは1KB = 1024バイトであることを意味しています。
では 2KB と入力した場合はどうなるでしょう?(2)
こちらは 2048 と表示されます。 2KB = 2048バイトを意味しています。
同様に MB(メガバイト) やGB(ギガバイト)の計算もできます。(3)(4)

sample2

PS C:\Work> 1KB ---(1)
1024
PS C:\Work> 2KB ---(2)
2048
PS C:\Work> 1MB ---(3)
1048576
PS C:\Work> 1GB ---(4)
1073741824
では、sample1の計算結果ををMBに変換してみましょう。(sample3)
1MBでわることで、2.1875(MB)と計算されて表示がされます。

sample3

PS C:\Work> $(Get-ChildItem "HIRO1.mdf").Length / 1MB
2.1875

15.ファイルの拡張子を取得する

Get-ChildItemコマンドレットは FileInfoオブジェクト を返します。
FileInfoクラスには 拡張子を取得するためのメソッド get_Extension がありますのでこれを使用します。
sample1のように Get-ChildItem コマンドレットの実行結果に対して get_Extension メソッドを実行すると拡張子を取得することができます。

sample1

PS C:\Work> $(Get-ChildItem "HIRO1.mdf").get_Extension()
.mdf

16.ファイルの絶対パスを取得する

Get-ChildItemコマンドレットは FileInfoオブジェクト を返します。
FileInfoクラスには 絶対パスを取得するためのプロパティ FullName がありますのでこれを使用します。
sample1のように Get-ChildItem コマンドレットの実行結果に対して FullName プロパティを使用すると絶対パスを取得することができます。

sample1

PS C:\Work> $(Get-ChildItem "HIRO1.mdf").FullName
C:\Work\HIRO1.mdf

17.ファイルの存在するディレクトリパスを取得する

Get-ChildItemコマンドレットは FileInfoオブジェクト を返します。
FileInfoクラスには ファイルの存在するディレクトリパスを取得するためのプロパティ DirectoryName がありますのでこれを使用します。
sample1のように Get-ChildItem コマンドレットの実行結果に対して DirectoryName プロパティを使用するとファイルの存在するディレクトリパスを取得することができます。

sample1

PS C:\Work> $(Get-ChildItem "HIRO1.mdf").DirectoryName
C:\Work

18.絶対パスからファイル名を取得する

Get-ChildItemコマンドレットは FileInfoオブジェクト を返します。
FileInfoクラスには 絶対パスからファイル名を取得するためのプロパティ Name がありますのでこれを使用します。
sample1のように Get-ChildItem コマンドレットの実行結果に対して Name プロパティを使用すると絶対パスからファイル名を取得することができます。

sample1

PS C:\Work> $(Get-ChildItem "C:\Work\HIRO1.mdf").Name
HIRO1.mdf

19.ファイルの拡張子を変更する

ファイルの拡張子を変更するには、System.IO.PathクラスのChangeExtensionメソッドを使用します。
sample1では、拡張子 txt を 拡張子 log へ変更したファイル名を取得しています。
ChangeExtensionメソッドは、実際のファイルの拡張子を変更するのではなく、変更した場合のファイル名を文字列として返すだけであることに注意してください。

sample1

PS C:\Work> [System.IO.Path]::ChangeExtension("sample1.txt",".log")
sample1.log
ChangeExtensionメソッドで拡張子を変更したファイ名を取得できることがわかりました。
今度は、これを利用して実際にファイルの拡張子を変更したいと思います。
拡張子を変更する前のファイル名を変数にセットします。(1)
拡張子変更後のファイル名を変数にセットします。(2)
Rename-Itemコマンドレットでファイル名を変更します。(3)

sample2

PS C:\Work> $oldfile = "sample1.txt" ---(1)
PS C:\Work> $newfile = [System.IO.Path]::ChangeExtension($oldfile, ".log") ---(2)
PS C:\Work> Rename-Item $oldfile $newfile ---(3)

20.ファイル内の文字列を置換する

PowerShellのファイル操作用コマンドレットはいくつかあるのですが、ファイル内の文字列を特定の文字列へ置換するコマンドレットは存在しません。
-replace演算子を使用して、ファイル内の文字列の置換を行う方法を紹介します。
まず、-replace 演算子の使用方法ですが
-replace "置換前の文字列" , "置換後の文字列"
という書式になっています。
-replace演算子は大文字と小文字を区別しません。
大文字と小文字を厳密に区別したい場合には、-creplace演算子を使用してください。
まずは実験をしてみたいと思います。
テキストエディタを開いて、下記のように入力して sample.txt として任意のフォルダへ保存してください。

sample.txt

ABCDE-FGHIJ-KLMNO
次に PowerShellでこのファイルの "FGHIJ" を "XXXXX" に置換して sample_new.txt というファイルへ保存してみたいと思います。
手順としては、
1.ファイルの内容を取得する
2."FGHIJ"を"XXXXX"に置換する
3.sample_new.txtへ保存する(リダイレクト演算子を使用します)
です。
これをPowerShellでは下記のように1行で実行することができます。

List1

PS C:\Work> $(Get-Content "C:\Work\sample.txt") -replace "FGHIJ","XXXXX" > sample_new.txt
先ほどは sample.txt の内容を置換し、sample_new.txt という別のファイルへ保存しました。
今度は、同一のファイルへ保存してみます。
List2のように入力して実行してみてください。
エラーになってしまったのではないでしょうか?
これは、Get-Contentで開いたファイルが閉じられないうちに、置換した結果を保存しようとするためにおこってしまったものです。

List2

PS C:\Work> $(Get-Content "C:\Work\sample.txt") -replace "FGHIJ","XXXXX" > "C:\Work\sample.txt"

Get-Content : 別のプロセスで使用されているため、プロセスはファイル 'C:\Work\sample.txt' にアクセスできません。
発生場所 行:1 文字:15
+ $(Get-Content <<<< "C:\Work\sample.txt") -replace "FGHIJ","XXXXX" > "C:\Work\sample.txt"

どうでしょうか、sample_new.txtの内容は下記のような結果になりましたか?

sample_new.txt

ABCDE-XXXXX-KLMNO
List3のように2行に分けて行えば、同一のファイルに対して置換した結果を書き込むことができます

List3

PS C:\Work> $file_contents = $(Get-Content "C:\Work\sample.txt") -replace "FGHIJ","XXXXX"
PS C:\Work> $file_contents > "C:\Work\sample.txt"
上記を踏まえて、Replace-Content という関数を作成してみました。
この関数を実行すると、文字列を置換し上書き保存を行います。
重要なファイルへの置換を行う場合には注意して使用してください。
確認メッセージの表示や、バックアップを取る機能を付加するとより実用的になるかと思います。

Replace-Content.ps1

#===============================================================================
# Replace-Content: ファイル内の指定文字列を置換する
# Param:
# $filepath : ファイルパス
# $rep1 : 置換対象文字列
# $rep2 : 置換後の文字列
#
# 使用例
# #sample.txtのファイル内の"AAA"という文字列を"BBB"に置換する
# Get-Content "C:\Work\sample.txt" "AAA" "BBB"
#
# copyright HIRO's.NET(http://hiro.wankuma.com/)
#===============================================================================
function global:Replace-Content
{
Param([string]$filepath, [string]$rep1, [string]$rep2)
if ( $(test-path $filepath) -ne $True )
{
Write-Error "存在しないパスです"
return
}
$file_contents = $(Get-Content $filepath) -replace $rep1, $rep2
$file_contents > $filepath
}
使用方法は下記の通りです

List4

PS C:\Work> Replace-Content "C:\Work\sample.txt" "AAA" "BBB"

21.ファイル名を変更する

ファイル名を変更するには Rename-Itemコマンドレットを使用します。
書式は
Rename-Item 名前を変更する項目のパス -newName 項目の新しい名前< /b>
です。
List1のように入力すると Test.txt を Test01.txt に変更することができます。

List1

PS C:\Work> Rename-Item Test.txt -newName Test01.txt

22.ファイルの内容を取得する

ファイルの内容を取得するには Get-Content コマンドレットを使用します。
書式は
Get-Content ファイル名
です。
List1のように入力すると Test.txtの中身が表示されます

List1

PS C:\Work> Get-Content Test.txt
List1のようにすると、テキストの内容を取得できることはわかりました。 しかし巨大なファイルで実行するとダラダラと表示されてしまいます。
最初の何行かを確認したいときには -totalCountパラメータ を使用します。
-totalCount は、内容を何行取得するかを指定します。
既定値はすべての行(-1)になっています。
使用方法はList2のとおりです。
List2では Test.txt の内容を10行取得して表示します。

List2

PS C:\Work> Get-Content Test.txt -totalCount 10

23.ファイルの末尾に文字列を追加する

Add-Contentコマンドレットを使用すると、ファイルの末尾に指定した文字列を追加することができます。
書式
Add-Content 対象のファイル 追加する文字列
です。
まずは、List1のように入力して I love PowerShell. と書かれた Test.txt を作成します。

List1

PS C:\Work> "I love PowerShell." > Test.txt
つぎに、Test.txt の末尾に現在日時を追加してみましょう。
List2のように入力してください。

List2

PS C:\Work> Add-Content Test.txt $(Get-Date)
Test.txtの中身は下記のようになります。

Test.txt

I love PowerShell.
2008/01/09 15:13:43
実はこのAdd-Contentコマンドレットは、複数のファイルに対して一括で処理を行うことが可能です。
List3のように入力すると、拡張子が *.txt のファイルの末尾に現在日時を書き込みます。

List3

Add-Content *.txt $(Get-Date).ToString()
-excludeパラメータ を使用すると、特定のファイルを除いて一括して文字列の追加を行うことが可能です。
たとえば Test01.txt, Test02.txt, Test03.txt, Test04.txt, Test05.txt の5つのファイルがあるとします。
Test03.txtを除いた他のファイルに対して現在日時文字列を追加したい場合はList4のようにします。
-excludeパラメータはワイルドカードも指定できるので
-exclude *03.txtのように書いても構いません。

List4

PS C:\Work4> Add-Content *.txt $(Get-Date).ToString() -exclude Test03.txt

25.ファイルに特定の文字列が含まれているかを検索する

grep は指定したファイルに対して文字列を検索するUNIX系OSで使われているコマンドです。
PowerShellでこれを実現できないか、考えてみました。
まず、Select-Stringというコマンドレットに注目してみました。
このコマンドレットは List1 のように入力すると"the"を含むファイルのリストを表示します。

List1

PS C:\Work> Select-String -path *.txt -pattern "the"
Test02.txt:5:the
Test04.txt:1:the
Select-Stringコマンドレットを使用すると、特定のファイルに対して文字列が含まれているかを検索することができます。
書式は
Select-String -path 検索するファイル 検索する文字列
です
List1 のように入力すると カレントディレクトリのテキストファイルに対して(*.txt) "the"を含むファイルを検索し結果を出力します。
この例では
Test02.txtの5行目
Test04.txtの1行目
に"the"があることを確認できます。
UNIXの grep に近い検索を行うことが可能ですね。
個人的にはとても重宝しているコマンドレットです。

List1

PS C:\Work> Select-String -path *.txt -pattern "the"
Test02.txt:5:the
Test04.txt:1:the

24.ファイルの行数をカウントする

ファイルの行数をカウントするには Get-Contentコマンドレットと Measure-Obejctコマンドレットの組み合わせで行うことができます。
List1のように入力すると Test01.txt ファイルの行数を取得することができます。

List1

PS C:\Work> $(Get-Content Test01.txt | Measure-Object).Count
2
上記を関数化してみたのが 下記の Get-LineCount.ps1 です。
使用方法は
Get-LineCount 行数をカウントするファイルのパス
です

Get-LineCoun.ps1

#===============================================================================
# Get-LineCount: 指定したファイルの行数を取得する
# Param:
# $filepath : 行数カウントを行うファイルのパス
#
# 使用例
# Get-LineCount Test.txt
#
# ヘルプを見る場合は
# Get-LineCount /?
#
# copyright HIRO's.NET(http://hiro.wankuma.com/)
#===============================================================================
function global:Get-LineCount
{
Param ([string]$filepath)
#ヘルプの参照か?
if ( $filepath -eq "/?" )
{
$helpmsg = @"
書式`r`n
Get-LineCount ファイル名
`r`n
使用例`r`n
#Test.txtの行数を取得
Get-LineCount `"Test.txt`"
#ヘルプを参照する
Get-LineCount /?
"@
Write-Host $helpmsg
return
}
$MeasureObject = Get-Content $filepath | Measure-Object
return $MeasureObject.count
}

01.ディレクトリを作成する

ディレクトリはエクスプローラからも作成できますが、PowerShellでの作成方法を覚えておくと便利です。
ディレクトリを作成するには、New-Itemコマンドレットを使用します。
書式は
New-Item -path ディレクトリを作成する場所 -name 作成するディレクトリ名 -type directory
です。
List1では C:\ に Workという名前のフォルダを作成します。

List1

PS C:> New-Item -path C:\ -name Work -type directory
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2008/01/22 15:38 Work
List2は、指定した日付をディレクトリ名として作成する例です。
ディレクトリ名は Get-Date コマンドレットで今日の日付を取得し "yyyyMMdd" という形で作成しています。
イベントログなどをスクリプトで日付ごとにディレクトリに分けて管理する場合などに役立つのではないでしょうか?

List2

PS C:> New-Item -path C:\ -name $(Get-Date).ToString("yyyyMMdd") -type directory
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2008/01/22 15:47 20080122

02.ディレクトリを移動する

ディレクトリを移動するには、Move-Itemコマンドレットを使用します。
書式は
Move-Item -path 移動元ディレクトリ -destination 移動先ディレクトリ
です。
List1を実行すると、C:\Work ディレクトリが C:\Work2の下へ移動します。
よって C:\Work2\Work ディレクトリが作成され、C:\Workディレクトリにあったファイルが C:\Work2\Workへすべて移動します。

List1

PS C:> Move-Item -path C:\Work -Destination C:\Work2

03.ディレクトリを削除する

ディレクトリを削除するには、Remove-Itemコマンドレットを使用します。
書式は
Remove-Item -path 削除するディレクトリ -recurse -force
です。
-pathパラメータ は、見ればわかるとおり削除するディレクトリを指定します。
-recurseパラメータ は、削除するディレクトリにサブディレクトリが含まれている場合、指定する必要があります。
-forceパラメータ ですが、このパラメータを指定しないと、ディレクトリ内に含まれる読み取り専用ファイルや隠し属性のついたファイルを削除することができず、結果としてディレクトリを削除することができません。
List1は、C:\Work5 ディレクトリを削除します

List1

PS C:\Work> Remove-Item -path C:\Work5 -recurse -force
List1を実行すると、確認メッセージを出さずにいきなり指定したディレクトリを削除してしまいます。
大事なディレクトリをうっかり消してしまわないよう、 -confirmパラメータ を付加し、確認メッセージを表示してから削除することをお勧めします。(List2)

List2

PS C:\Work> Remove-Item -path C:\Work5 -recurse -force -confirm
確認
この操作を実行しますか?
対象 "C:\Work5" に対して操作 "ディレクトリの削除" を実行しています。
[Y] はい(Y) [A] すべて続行(A) [N] いいえ(N) [L] すべて無視(L) [S] 中断(S) [?] ヘルプ (既定値は "Y"):

04.ディレクトリをコピーする

ディレクトリをコピーするには Copy-Itemコマンドレットを使用します。
書式は
Copy-Item コピー元ディレクトリ -destination コピー先ディレクトリ -recurse
です。
-recurseパラメータ は、ヘルプによると「再帰的なコピーを指定します」とあります。
しかし、このパラメータを外すと、サブディレクトリはおろかファイルすらもコピーされなくなるので注意が必要です。
List1では C:\Workフォルダを C:\Work2 へ全てのファイルと全てのサブディレクトリをコピーします。
コピー先ディレクトリが存在しない場合は、自動で作成されます。

List1

PS C:\Work> Copy-Item C:\Work -destination C:\Work2 -recurse

05.ディレクトリの存在を確認する

ディレクトリの存在を確認するには Test-Pathコマンドレットを使用します。
書式は
Test-Path 存在を確認するディレクトリパス
です。
指定したディレクトリが存在する場合にはTrueを、存在しない場合にはFalseを返します。
List1では C:\Work ディレクトリの存在を確認しています。

List1

PS C:\Work3> Test-Path C:\Work
True

06.ディレクトリの作成日時の取得/設定を行う

ディレクトリの作成日時を取得するには Get-ItemPropertyコマンドレットを使用します。
作成日を取得する場合の書式は
(Get-ItemProperty 作成日時を取得するディレクトリのパス ).CreationTime
です。
List1では C:\Work ディレクトリの作成日時を取得しています。

List1

PS C:\Users\HIRO> (Get-Itemproperty C:\Work).CreationTime
2007年6月4日 23:28:11
ディレクトリの作成日の設定も、Get-ItemPropertyコマンドレットを使用します。
作成日時を設定する場合の書式は
(Get-Itemproperty 作成日時を設定するディレクトリのパス ).set_CreationTime(設定する作成日時)
です。
List2では C:\Work の作成日時を現在の日時に設定しています。

List2

PS C:\Users\HIRO> (Get-Itemproperty C:\Work).set_CreationTime($(Get-Date))
List2では現在の日時を作成日時としました。
今度は、任意の日時をディレクトリの作成日時に設定する方法を紹介します。
まずは任意の日時の入った変数を作成します。
任意の日時が入った変数を作成するには List3のようにします。
ダブルクォーテーションの内側に任意の日時を示す文字列を指定します。

List3

PS C:\Users\HIRO> $dt = Get-Date "2008/02/01 10:00:00"
次に、List2と同様のやり方で、set_CreationTimeメソッドの引数に、先ほどの変数をセットすることで、任意の日時を作成日時にすることができます。

List4

PS C:\Users\HIRO> (Get-Itemproperty C:\Work).set_CreationTime($dt)

07.ディレクトリの更新日時の取得/設定を行う

ディレクトリの更新日時を取得するには Get-ItemPropertyコマンドレットを使用します。
更新日時を取得する場合の書式は
(Get-ItemProperty 更新日時を取得するディレクトリのパス ).LastWriteTime
です。
List1では C:\Work ディレクトリの更新日時を取得しています。

List1

PS C:\Users\HIRO> (Get-ItemProperty C:\Work).LastWriteTime
2008年1月30日 23:10:47
ディレクトリの更新日時の設定も、Get-ItemPropertyコマンドレットを使用します。
更新日時を設定する場合の書式は
(Get-Itemproperty 更新日時を設定するディレクトリのパス ).set_LastWriteTime( 設定する更新日時 )
です。
List2では C:\Work の更新日時を現在の日時に設定しています。

List2

PS C:\Users\HIRO> (Get-Itemproperty C:\Work).set_LastWriteTime($(Get-Date))
今度は、任意の日時をディレクトリの更新日時に設定する方法を紹介します。
まずは任意の日時の入った変数を作成します。
任意の日時が入った変数を作成するには List3のようにします。
ダブルクォーテーションの内側に任意の日時を示す文字列を指定します。

List3

PS C:\Users\HIRO> $dt = Get-Date "2008/02/01 10:00:00"
次に、List2と同様のやり方で、set_LastWriteTimeメソッドの引数に、先ほどの変数をセットすることで、任意の日時を更新日時にすることができます。

List4

PS C:\Users\HIRO> (Get-Itemproperty C:\Work).set_LastWriteTime($dt)

08.ディレクトリのアクセス日時の取得/設定を行う

ディレクトリのアクセス日時を取得するには Get-ItemPropertyコマンドレットを使用します。
アクセス日時を取得する場合の書式は
(Get-ItemProperty アクセス日時を取得するディレクトリのパス ).LastAccessTime
です。
List1では C:\Work ディレクトリのアクセス日時を取得しています。

List1

PS C:\Users\HIRO> (Get-ItemProperty C:\Work).LastAccessTime
2008年1月30日 23:10:47
ディレクトリのアクセス日時の設定も、Get-ItemPropertyコマンドレットを使用します。
アクセス日時を設定する場合の書式は
(Get-Itemproperty 更新日時を設定するディレクトリのパス ).set_LastAccessTime( 設定するアクセス日時 )
です。
List2では C:\Work のアクセス日時を現在の日時に設定しています。

List2

PS C:\Users\HIRO> (Get-Itemproperty C:\Work).set_LastAccessTime($(Get-Date))
今度は、任意の日時をディレクトリのアクセス日時に設定する方法を紹介します。
まずは任意の日時の入った変数を作成します。
任意の日時が入った変数を作成するには List3のようにします。
ダブルクォーテーションの内側に任意の日時を示す文字列を指定します。

List3

PS C:\Users\HIRO> $dt = Get-Date "2008/02/01 10:00:00"
次に、List2と同様のやり方で、set_LastAccessTimeメソッドの引数に、先ほどの変数をセットすることで、任意の日時をアクセス日時にすることができます。

List4

PS C:\Users\HIRO> (Get-Itemproperty C:\Work).set_LastAccessTime($dt)

09.ルートディレクトリを取得する

現在の作業場所のルートディレクトリを取得するには Get-Locationコマンドレットを使用します。
書式は
(Get-Location).Drive.Root
です。
List1ではカレントディレクトリが C:\Work で実行しているので、ルートディレクトリとして C:\ を返します。

List1

PS C:\Work3> (Get-Location).Drive.Root
C:\
今度は、任意のパス文字列からルートディレクトリを取得してみたいと思います。
残念ながら、既存のコマンドレットの機能で取得する方法は思いつきませんでしたので、.NET Frameworkを使用した例を紹介します。
まず最初にSystem.IO.DirectoryをLoadします。(List1)

List2

PS C:\Work> [reflection.assembly]::LoadWithPartialName("System.IO")
つぎに、System.IO.DirectoryのGetDirectoryRootメソッドを使用して、ルートディレクトリを取得します。
書式
[System.IO.Directory]::GetDirectoryRoot( パス文字列 )
です。
List3では、"C:\Work"のルートディレクトリと"F:\Work"のルートディレクトリを取得しています。
GetDirectoryRootメソッドでは、パス文字列で指定したパスは、実際に存在する必要はありません。
架空のパスでも実行することができるため、場合によっては存在するパスかどうかを確認する処理を含める必要があります。(この場合にはTest-Pathコマンドレットが有効です)

List3

PS C:\Work> [System.IO.Directory]::GetDirectoryRoot("C:\Work")
C:\
PS C:\Work> [System.IO.Directory]::GetDirectoryRoot("F:\Work")
F:\

10.指定したディレクトリのサブディレクトリを取得する

つぎに、.NET Frameworkを利用した方法を紹介します。
指定したディレクトリ以下にあるサブディレクトリを取得するには、System.IO.DirectoryのGetDirecoriesメソッドを使用することで取得することができます。
まず最初にSystem.IOをロードします。

List2

PS C:\Work> [reflection.assembly]::LoadWithPartialName("System.IO")
つぎに、GetDirectoriesメソッドを使用して、任意のディレクトリ以下にあるサブディレクトリを取得します。
書式は
[System.IO.Directory]::GetDirectories(" 任意のディレクトリ ")
です。
List3では、"C:\Work"以下にあるサブディレクトリを取得しています。

List2

PS C:\Work> [System.IO.Directory]::GetDirectories("C:\Work")
C:\Work\256835_PSTemplates
C:\Work\ACS001
C:\Work\ACS002
C:\Work\ACS003
C:\Work\ACS004
C:\Work\ACS005
まず、サブディレクトリを取得する方法ですが、Get-ChildItemコマンドレットを使用します。
get-ChildItemコマンドレットを単独で実行すると、左から順にMode, LastWriteTime, Length, Nameの順に表示されます。
Modeが"d----"と表示されているのがディレクトリですので、パイプを使用してディレクトリだけに絞り込みたいと思います。
書式は
Get-ChildItem -path " 任意のフォルダ " | where { $_.mode -match "d" }
です。
リスト1ではC:\Workのサブディレクトリを取得しています。

List1

PS C:\Work> Get-ChildItem -path C:\Work | where { $_.mode -match "d" }
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\Work
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2007/12/25 10:59 256835_PSTemplates
d---- 2007/11/09 11:02 ACS001
d---- 2007/08/28 14:53 ACS002
d---- 2007/08/28 14:53 ACS003
d---- 2007/08/28 14:53 ACS004
d---- 2007/08/28 14:53 ACS005
d---- 2007/08/28 14:54 Backup

11.論理ドライブを取得する

論理ドライブを取得するには Get-PSDriveコマンドレットを使用します。
ただし、Get-PSDriveコマンドレットを単独で実行すると、List1のような結果となり、PowerShellでドライブとして扱っているものの一覧が表示されてしまいます。

List1

PS C:\Work> Get-PSDrive
Name Provider Root
---- -------- ----
A FileSystem A:\
Alias Alias
C FileSystem C:\
cert Certificate \
D FileSystem D:\
E FileSystem E:\
Env Environment
F FileSystem F:\
Function Function
G FileSystem G:\
HKCU Registry HKEY_CURRENT_USER
HKLM Registry HKEY_LOCAL_MACHINE
S FileSystem S:\
T FileSystem T:\
U FileSystem U:\
V FileSystem V:\
Variable Variable
W FileSystem W:\
X FileSystem X:\
Y FileSystem Y:\
Z FileSystem Z:\
そこで、Where-Objectコマンドレットを使用して、論理ドライブだけを取得したいと思います。
論理ドライブは Providerが"FileSystem"のものだけを抜き出せば良いので、
書式は
Get-PSDrive | Where { $_.Provider -match "FileSystem"}
となります。
これを実行すると
List2のようにGet-PSDriveコマンドレットの実行結果から、論理ドライブを取得することができます。

List2

PS C:\Work> Get-PSDrive | Where { $_.Provider -match "FileSystem"}
Name Provider Root
---- -------- ----
A FileSystem A:\
C FileSystem C:\
D FileSystem D:\
E FileSystem E:\
F FileSystem F:\
G FileSystem G:\
S FileSystem S:\
T FileSystem T:\
U FileSystem U:\
V FileSystem V:\
W FileSystem W:\
X FileSystem X:\
Y FileSystem Y:\
Z FileSystem Z:\

12.特別なディレクトリを取得する

特別なディレクトリ(マイドキュメントやデスクトップ)のディレクトリパスを取得するには、System.EnvironmentクラスのGetFolderPathメソッドを使用します。
まず最初に、System.Environmentをロードします。(List1)

List1

PS C:\Work> [reflection.assembly]::LoadWithPartialName("System.Environment")
次に GetFolderPathメソッドを使用して特別なディレクトリを取得します。
GetFolderPathメソッドの引数にはEnvironment,SpecialFolder列挙体を指定します。
List2ではマイドキュメントディレクトリのパスを取得しています。
メンバ名 説明
ApplicationData 現在のローミング ユーザーのアプリケーション固有のデータの共通リポジトリとして機能するディレクトリ。
ローミング ユーザーは、ネットワーク上の複数のコンピュータで作業します。ローミング ユーザーのプロファイルはネットワーク上のサーバーで保持され、ユーザーがログオンするとシステムに読み込まれます。
CommonApplicationData すべてのユーザーが使用するアプリケーション固有のデータの共通リポジトリとして機能するディレクトリ。
CommonProgramFiles アプリケーション間で共有されるコンポーネント用のディレクトリ。
Cookies インターネット cookies の共通リポジトリとして機能するディレクトリ。
Desktop 物理的なファイル システム上の場所ではない論理的なデスクトップ。
DesktopDirectory デスクトップ上のファイル オブジェクトを物理的に格納するために使用されるディレクトリ。
仮想フォルダであるデスクトップ フォルダ自体とこのディレクトリ フォルダを混同しないようにしてください。
Favorites ユーザーのお気に入り項目の共通リポジトリとして機能するディレクトリ。
History インターネットの履歴項目の共通リポジトリとして機能するディレクトリ。
InternetCache 一時インターネット ファイルの共通リポジトリとして機能するディレクトリ。
LocalApplicationData 現在の非ローミング ユーザーが使用するアプリケーション固有のデータの共通リポジトリとして機能するディレクトリ。
MyComputer マイ コンピュータ フォルダ。
メモ
マイ コンピュータ フォルダに対するパスが定義されていないので、MyComputer定数は、常に空の文字列 ("") を生成します。
MyDocuments マイ ドキュメント フォルダ。 ;
MyMusic マイ ミュージック フォルダ。
MyPictures マイ ピクチャ フォルダ。
Personal ドキュメントの共通リポジトリとして機能するディレクトリ。
ProgramFiles プログラム ファイル ディレクトリ。
Programs ユーザーのプログラム グループを格納するディレクトリ。
Recent ユーザーが最近使用したドキュメントを格納するディレクトリ。
SendTo [送る] メニュー項目を格納するディレクトリ。
StartMenu [スタート] メニュー項目を格納するディレクトリ。
Startup ユーザーの [スタート アップ] プログラム グループに対応するディレクトリ。
ユーザーが Windows NT 以降のバージョンの Windows にログオンするか、それを起動するか、または Windows 98 を起動すると、これらのプログラムが起動されます。
System System ディレクトリ。
Templates ドキュメント テンプレートの共通リポジトリとして機能するディレクトリ。

List2

C:\Work> [System.Environment]::getFolderPath([System.Environment+SpecialFolder]::MyDocuments)
C:\Documents and Settings\HIRO\My Documents

01.パスの結合

パスを結合するには Join-Pathコマンドレットを使用します。
書式は
Join-Path -path 親のパス -childpath 子のパス
です。
パラメータ -path と -childpath は省略可能ですので
書式を
Join-Path 親のパス 子のパス
と記述することも可能です。
なお、パスの区切り記号はプロバイダによって追加されます。
List1では C:\Work と Backupを連結し C:\Work\Backup というパスを作成します。
このコマンドレットの実行で C:\Work と Backup との間に自動でパス区切り文字 "\" が挿入されていることがわかります。

List1

PS C:\Work> Join-Path C:\Work Backup
C:\Work\Backup
つぎに C:\Work\ と \Backup という文字列を連結してみたいと思います。(List2)
実行してみるとわかるとおり、単純に "C:\Work\" と "\Backup" を連結して "C:\Work\\Backup" とするのではなく、パスとして有効な文字列 "C:\Work\Backup" にして返すようになっています。

List2

PS C:\Work> Join-Path C:\Work\ \Backup
C:\Work\Backup
最後に実例ですが、C:\Work の下に今日の日付をディレクトリ名にしたパスを作成し、実際にそのディレクトリを作成してみたいと思います。
ます、今日の日付(書式:yyyyMMdd)を文字列として取得するには
(Get-Date).ToString("yyyyMMdd")とします。
よって
Join-Path C:\Work (Get-Date).ToString("yyyyMMdd")
とすることで、目的のパスを取得することができます。
とりあえずこれを変数 $a に代入しましょう。
次にディレクトリの作成ですが New-Itemコマンドレットを使用します。(Tips: ディレクトリを作成する を参照)
New-Item -path $a -type directory
とすれば、今日の日付のディレクトリが C:\Workに作成されます。(List3)

List3

PS C:\Work> $a = Join-Path C:\Work (Get-Date).ToString("yyyyMMdd")
PS C:\Work> New-Item -path $a -type directory
ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\Work
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2008/02/15 14:06 20080215

02.パスからドライブ文字を取得する

パスからドライブ文字を取得するには Split-Path コマンドレットを使用します。
書式は
Split-Path "パス文字列" -qualifier
です。
List1は パス文字列に C:\Work を指定していますので、結果として "C:" が返されます。
注意:パス文字列は、ダブルクォーテションで括らなくても指定可能ですが、空白を含むパス文字列の場合は必ずダブルクォーテションで括るようにしてください。
同様のTipsに ルートディレクトリを取得 するがあります。ただしこちらはディレクトリなので C:\ が返されます。

Lsit1

PS C:\Work> Split-Path "C:\Work" -Qualifier
C:

03.パスから親パスを取得する

うまいタイトルが見つけられず、内容を想像できなかったかもしれません。
ここでいう「パスから親パスを取得する」とは
C:\Test\Logs\Pass1.log
の一番末端の Pass1.log の親パスを取得することを意味しています。
これを実現するには Split-Pathコマンドレットを使用します。
この場合の書式は
Split-Path パス文字列 -parent
とします。
List1ではパスに C:\Test\Logs\Pass1.log を指定しているので、親パスとして C:\Test\Logs が返されます。

List1

PS C:\Work> Split-Path "C:\Test\Logs\Pass1.log" -Parent
C:\Test\Logs

04.パスから最後の項目部分を取得する

「パスから最後の項目部分を取得する」とは、
たとえばパスが
C:\Test\Logs\ Pass1.log
の場合は、 Pass1.log
C:\Test\ Logs
の場合は、 Logs を取得することを意味します。
これを実現するには Split-Path コマンドレットを使用します。
このときの書式は
Split-Path "パス文字列" -leaf
です。
List1では "C:\Test\Logs\Pass1.log" から Pass1.Log を取得しています。

List1

PS C:\Work> Split-Path "C:\Test\Logs\Pass1.log" -leaf
Pass1.log
List2では "C:\Test\Logs" から Logs を取得しています。

List2

PS C:\Work> Split-Path "C:\Test\Logs" -leaf
Logs

05.パスが絶対パスかどうかを判定する

パスが絶対パスかどうかを判定するには Split-Pathコマンドレットを使用します。
書式は
Split-Path "絶対パスかどうかを判定するパス文字列" -isAbsolute
です。
パスが絶対パスの場合は TRUE を返し、相対パスの場合は FALSE を返します。
なお、指定するパスは実在する必要はありません。
List1では相対パスを指定しているため、Falseが返されています。

List1

PS C:\Work> split-path ".\My Pictures\*.jpg" -IsAbsolute
False
List2では、絶対パスを指定しているので True が返されています。

List2

PS C:\Work> split-path "C:\Users\Hiro\My Pictures\*.jpg" -IsAbsolute
True

06.パスが存在するか確認する

パスが存在するかどうかを確認するには、Test-Path コマンドレットを使用します。
書式は
Test-Path "存在を確認するパス"
です。
パスが存在する場合には True を返し、存在しない場合には False を返します。

List1

PS C:\Work> Test-Path "C:\Work"
True
PS C:\Work> Test-Path "C:\WorkWork"
False

07.パスの構文が正しいか確認する

パスの構文が正しいかを確認するには、Test-Path コマンドレットを使用します。
書式は
Test-Path "構文が正しいかを確認するパス" -IsValid
です。
構文を確認するために -IsValid パラメータ を使用した場合には、指定したパスは存在しなくても構いません。
構文が正しい場合には True を返し、正しくない場合には False を返します。

List1

PS C:\Work> Test-Path "C:\Work" -IsValid
True
PS C:\Work> Test-Path "C:\Work\\Directory"
False

01.XMLファイルを変数に読み込む

PowerShellでXMLファイルを読み込む方法の1つとして、Get-Contentコマンドレットを使用することが可能です。
List1のように記述すると、変数 $doc にXMLファイルが読み込まれます。
先頭に[xml]を付けることによって、XmlDocument型の変数になります。

List1

PS C:\Work> [xml]$doc = Get-Content "C:\Work\Test.xml"
List1ではエンコーディングを指定しませんでした。
実際に読み込む場合には、エンコーディングを指定することをおすすめします。
エンコーディングを指定するには、-encodingパラメータを使用します。
-encodingパラメータには
・Unicode
・UTF7
・UTF8
・UTF32
・ASCII
・BigEndianUnicode
・Default
・OEM
を指定することができます。
UTF8で読み込むにはList2のように記述します。

List2

PS C:\Work> [xml]$doc = Get-Content "C:\Work\Test.xml" -encoding UTF8

02.文字列からXMLファイルを作成する

文字列からXMLファイルを作成する方法を、順を追って説明します。
まず、XML文字列を作成し、変数に代入します。
複数行にわたる(改行のある)文字列を変数に代入するには、ヒア文字列を使用します。
ヒア文字列は @" ~ "@ で括ります。

List1

PS C:\Work> $strXml = @"
>> <?xml version='1.0' ?>
>> <personal_data>
>> <zip_code>012-3456</zip_code>
>> <address>1-1, Tokyo, Japan</address>
>> <name>HIRO</name>
>> </personal_data>
>> "@
>>
次に、List1で代入した文字列をXmlDocumento型にキャストします。(List2)

List2

PS C:\Work> $xmlDoc = [xml]$strXml
ここまでで、すでにXMLドキュメントは完成しています。
最後に、作成されたXmlドキュメントをファイルに書き込みます。
ファイルへの書き込みは Saveメソッドを使用します。

List3

PS C:\Work> $xmlDoc.Save("C:\Work\Test.xml")
作成されたxmlファイルは下記のようになります。
この方法で保存すると、自動でインデントされます。

Test.xml

<?xml version='1.0'?>
<personal_data>
<zip_code>012-3456</zip_code>
<address>1-1, Tokyo, Japan</address>
<name>HIRO</name>
</personal_data>

03.Encodingを指定してXMLファイルを作成する

文字列からXMLファイルを作成する では、Xmlファイルを作成する際、Encodingを指定しませんでした。
このTipsでは、Encodingを指定してのXmlファイル作成方法について説明します。
まずは、保存先ファイル名とEncodingを変数へ代入します。

List1

PS C:\Work> $SaveFile = "C:\Work\UTF8.xml"
PS C:\Work> [System.Text.Encoding]::UTF8
List1ではEncodingにUTF8を代入しましたが、Shift_Jisを使用する場合には GetEncodingメソッドを使用してList2のようにします。

List2

PS C:\Work> $Encoding = [System.Text.Encoding]::GetEncoding("Shift_Jis")
次に、XML文字列を変数 $strXml へ代入します。( 文字列からXMLファイルを作成する )

List3

PS C:\Work> $strXml = @"
>> <?xml version='1.0' ?>
>> <personal_data>
>> <zip_code>012-3456</zip_code>
>> <address>1-1, Tokyo, Japan</address>
>> <name>HIRO</name>
>> </personal_data>
>> "@
>>
作成した文字列を XmlDocument型へキャストします。(List4)

List4

PS C:\Work> $xmlDoc = [xml]$strXml
UTF8 にエンコードした XmlTextWriter を作成します。

List5

PS C:Work> $xmlWriter = New-Object System.Xml.XmlTextWriter($SaveFile, $Encoding)
最後に、ファイルに保存して、XmlTextWriterを閉じます。

List6

PS C:\Work> $XmlDoc.Save($xmlWriter)
PS C:\Work> $xmlWriter.Close()

01.現在日時からファイル名を作成する

PowerShellで現在日時を取得するには Get-Dateコマンドレットを使用します。
まず最初にGet-Dateコマンドレットを利用して、現在日時(たとえば2008/04/27 10:12:23という日時)から20080427_1012023.txtのようなファイル名を、コマンドラインから作成してみたい音思います。

List1

PS > $filename = $(Get-Date).ToString("yyyyMMdd_hhmmss") + ".txt"
上記を再利用しやすくするため関数にしたのが下記です。

Get-DateFilename.ps1

#===============================================================================
# Get-DateFilename: 現在日時でファイル名を作成した文字列を返す
# Param:
# $extension : ファイル名につける拡張子(ドットは付けても付けなくても良い)
#
# 使用例
# #現在日時でテキストファイル名を作成する
# Get-DateFileName ".txt"
#
# ヘルプを見る場合は
# Get-DateFileName /?
#
# copyright HIRO's.NET(http://blog.hiros-dot.net/)
#===============================================================================
function global:Get-DateFileName {
Param ([string]$extension)
#ヘルプの参照か?
if ( $extension -eq "-?" )
{
$helpmsg = @"
書式`r`n
Get-DateFileName`" 付加する拡張子`"`r`n
`r`n
使用例`r`n
#現在日時でテキストファイル名を作成する
Get-DateFileName `".txt`"
#ヘルプを参照する
Get-DateFileName /?
"@
Write-Host $helpmsg
return
}
#パラメータが指定されていて且つ先頭にドットがない場合
if ( ($extension.length -gt 0) -and (-not $extension.StartsWith(".")) )
{
#ドット + 拡張子
$extension = "." + $extension
}
return $($(Get-Date).ToString("yyyyMMdd_hhmmss") + $extension)
}
使用方法は、拡張子が.txtのファイル名を作成する場合は

List2

PS > Get-DateFileName ".txt"
使用方法を参照したい場合は下記のように入力してください。

List3

PS > Get-DateFileName -?

02.ファイルの拡張子を変更する

ファイルの拡張子を変更するには、System.IO.PathクラスのChangeExtensionメソッドを使用します。
これを利用して、拡張子を変更する関数を作成してみました。

Change-Extension.ps1

#===============================================================================
# Change-Extension: ファイルの拡張子を変更する
# Param:
# $path : 拡張子を変更するファイル
# $newExtension: 変更後の拡張子
# $echo : "on"を指定すると変更履歴を表示。規定値は"off"
#
# 使用例
# #sample1.txt の拡張子を.bakに変更する
# Change-Extension "sample1.txt" "bak"
#
# #sample1.txt と sample2.txt の拡張子を.bakに変更する
# Change-Extension "sample1.txt","sample2.txt" "bak"
#
# ヘルプを見る場合は
# Change-Extension -?
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:Change-Extension
{
Param ([String[]]$path, [String]$newExtension, [String]$echo="off")
#ヘルプの参照か?
if ( $path -eq "-?" -or $newExtension -eq "-?" -or $echo -eq "-?" )
{
$helpmsg = @"
書式`r`n
Change-Extension [`$path], [`$newExtension], [`$echo ]`r`n
パラメータ`r`n
`$path
拡張子を変更する項目のパスを指定します。`r`n
`$newExtension
変更後の拡張子を指定します`r`n
`$echo
変更履歴を表示する場合は`"on`"を指定します。規定値は`"off`"です。`r`n
`r`n
使用例`r`n
#sample1.txt の拡張子を.bakに変更する
Change-Extensio `"sample1.txt`" `"bak`"
#sample1.txt と sample2.txt の拡張子を.bakに変更する
Change-Extensio `"sample1.txt`",`"sample2.txt`" `"bak`"
#変更履歴を表示する
Change-Extension "sample1.txt" "bak" "on"
#ヘルプを参照する
Get-DateFileName /?
"@
Write-Host $helpmsg
return
}
foreach ( $file in $path )
{
#拡張子返還後のファイル名を取得
$newfile = [System.IO.Path]::ChangeExtension($file, $newExtension)
#ファイル名を変更する
if ( Test-Path $file )
{
Rename-Item $file $newfile
# $echo が "on"なら変換結果を表示
if ( $echo -eq "on" )
{
Write-Host ($file + " --> " + $newfile)
}
}
elseif ( $echo -eq "on" )
{
Write-Host ($file + " は存在しませんでした")
}
}
}
使用方法ですが、sample1.txt の拡張子を.bakに変更するには

List1

PS > Change-Extension "sample1.txt" "bak"
sample1.txt と sample2.txt の2つのファイルの拡張子を.bakに変更するには

List2

PS > Change-Extension "sample1.txt","sample2.txt" "bak"
ヘルプを参照するには、下記のようにします。

List3

PS > Change-Extension -?

03.HTTPダウンロードする

PowerShellでHTTPダウンロードするには、System.Net.WebClient クラスを使用します。
下記は、http://hiros-dot.net/ にあるinedex.htmlファイルを C:\Workにindex.htmlという名前で保存します。

List1

PS > $webClient = new-object System.Net.WebClient
PS > $webClient.DownloadFile("http://hirosdot.net/index.html", "C:\Work\index.html")
上記を再利用しやすくするために、関数化したものが下記です。

Download-File.ps1

#===============================================================================
# Download-File: HTTPダウンロードする
# Param:
# $url : ダウンロードするファイルURL
# $SaveDir : 保存先ディレクトリ(省略した場合はカレントディレクトリ)
# $filename : 保存ファイル名(省略した場合はダウンロードしたファイル名となる)
#
# ヘルプを見る場合は
# Download-File /?
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:Download-File
{
Param ([string]$url, [string]$SaveDir, [string]$filename)
#ヘルプの参照か?
if ( $url -eq "-?" )
{
$helpmsg = @"
書式`r`n
Download-File [`$url] [[`$SaveDir]] [[`$filebame]]`r`n
パラメータ`r`n
`$url
ダウンロードするファイルURL`r`n
`$SaveDir
ダウンロードしたファイルを保存するディレクトリ
省略した場合はカレントディレクトリに保存します`r`n
`$filename
保存ファイル名
省略した場合はダウンロードしたフィル名となります`r`n
`r`n
使用例`r`n
# http://hiros-dot.net/index.html をダウンロードする
# この場合はカレントディレクトリに index.html というファイル名で保存される
Download-File "http://hiros-dot.net/index.html"
#指定したディレクトリに保存する
Download-File "http://hiros-dot.net/index.html" "C:\Work"
#指定したディレクトリに名前を付けて保存する
#この場合は C:\Work に sample1.html という名前で保存する
Download-File "http://hiros-dot.net/index.html" "C:\Work" "sample1.html"
#ヘルプを参照する
Get-DateFileName /?
"@
Write-Host $helpmsg
return
}
$webClient = new-object System.Net.WebClient
#保存先が指定されていない場合
if ( $SaveDir.Length -eq 0 )
{
#カレントディレクトリを保存先にする
$SaveDir = $(get-location).Path
}
#保存ファイル名が指定されていない場合
if ( $filename.Length -eq 0 )
{
#指定されたURLからファイル名を取得
$uri = new-object Uri($url)
$filename = $uri.Segments[$uri.Segments.Length-1]
}
if ( $filename -eq "/" )
{
Write-Host "ダウンロードできません。`r`nURLはファイル名を含めて指定してください!!" -foregroundcolor red
return
}
#保存先パス文字列の作成
$filePath = [System.IO.Path]::Combine($SaveDir, $filename)
#ダウンロードする
$webClient.DownloadFile($url,$filePath)
}
この関数の書式は
Download-File ダウンロードするファイルURL 保存先ディレクトリ 保存ファイル名
です。
下記のように、URLだけを指定した場合は、対象ファイルをカレントディレクトリに保存します。

List2

Download-File "http://hiros-dot.net/index.html"
URLと保存先だけを指定することもできます。

List3

PS > Download-File "http://hiros-dot.net/index.html" "c:\Work"
任意の名前をつけて保存する場合は、第3引数にファイル名を指定します。

List4

PS > Download-File "http://hiros-dot.net/index.html" "C:\Work" "sample1.html"
ヘルプの表示は下記のようにします。

List5

PS > Download-File -?

04.指定したファイルの行数をカウントする

Get-Content コマンドレットは、ファイルに格納されているテキストなど、パスで指定された場所にある項目の内容を取得するコマンドレットですが、この結果をパイプを通してMeasure-Objectコマンドレットに渡すことで、ファイルの行数を取得することができるようになります。
Get-LineCount という関数を作成したので、下記に紹介します。

Get-LineCount

#===============================================================================
# Get-LineCount: 指定したファイルの行数を取得する
# Param:
# $filepath : 行数カウントを行うファイルのパス
#
# 使用例
# Get-LineCount Test.txt
#
# ヘルプを見る場合は
# Get-LineCount /?
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:Get-LineCount
{
Param ([string]$filepath)
#ヘルプの参照か?
if ( $filepath -eq "/?" )
{
$helpmsg = @"
書式`r`n
Get-LineCount ファイル名
`r`n
使用例`r`n
#Test.txtの行数を取得
Get-LineCount `"Test.txt`"
#ヘルプを参照する
Get-LineCount /?
"@
Write-Host $helpmsg
return
}
$MeasureObject = Get-Content $filepath | Measure-Object
return $MeasureObject.count
}
使用方法はList1の通りです。

List1

PS C:\Users\HIRO> Get-LineCount "Test.txt"
12
ヘルプの表示は下記のようにします。

List2

PS > Get-LineCount -?

05.Oracleデータベースからデータを取得してXMLへ保存する

Windows PowerShellからOracleへアクセスし、取得したデータをXMLファイルへ落とし込む関数を作ってみました。

Export-OracleDataXml.ps1

#===============================================================================
# Export-OracleDataXml: データを取得してXMLファイルへ保存する(Oracle)
#
# 使用例
# PS > Export-OracleDataXml
# PS > DataSource: データソース名
# PS > User ID: ユーザーID
# PS > Password: パスワード
# PS > Query String: クエリ文字列
# PS > Save Path: 保存先を指定
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:Export-OracleDataXml
{
#===== 必要情報をユーザーから取得する =====
$DataSource = Read-Host "Data Source"
$UserID = Read-Host "User ID"
$Password = Read-Host "Password" -assecurestring
$QueryString = Read-Host "Query String"
$SavePath = Read-Host "Save Path"
#保存先パスに"\"が含まれていない場合(つまりファイル名のみが指定されていた場合)は
#絶対パスにする(ファイル名のみが指定された場合、カレントディレクトリに保存するため)
if ( $SavePath.IndexOf("\") -eq -1 )
{
$SavePath = $(Join-Path $(Get-Location).Path $SavePath)
}
#===== newpopsさんのblog参照 http://d.hatena.ne.jp/newpops/20050923/p1 =====
#SecureStringからパスワード文字列を取得する
$ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password)
$pass = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($ptr)
#===== Oracleからのデータ取得とファイルへの保存 =====
[reflection.assembly]::LoadWithPartialName("System.Data.OracleClient")
$ConnectionString = "Data Source=" + $DataSource + ";User ID=" + $UserID + ";Password=" + $Pass + ";Integrated Security=no;"
$OraConn = New-Object System.Data.OracleClient.OracleConnection($ConnectionString)
$dtSet = New-Object System.Data.DataSet
$OraDa = New-Object System.Data.OracleClient.OracleDataAdapter($QueryString, $OraConn)
$OraDa.Fill($dtSet)
$dtSet.WriteXml($SavePath)
}
使用方法ですが下記のようにコマンドラインで関数名を入力します。

List1

PS C:\Work> Export-OracleDataXml
つぎに、接続先、ユーザー名、パスワード、データを取得するためのselect文、取得データの保存先を聞かれるので順番に入力していきます。
下記はOracleのサンプルであるscott/tigerのemp表データをすべて取得し、結果をC:\Work\emp.xmlへ保存する例です

List2

Data Source: YourServer
User ID: scott
Password: *****
Query String: select * from emp
SavePath: C:\Work\emp.xml
===== ポイント =====
今回の関数は対話式にしてみました。
1)Read-Hostコマンドレットを使用して、ユーザーからの入力を取得して、変数へ代入しています。
Read-Hostコマンドレットは
$a = Read-Host "メッセージ"
のように使用します。
この場合は、コンソールに "メッセージ:" と表示され
ユーザーが[Enter]を押すまでの文字列を$aに代入します。
2)SecureStringでパスワードを*で表示する
Read-Hostコマンドレットのパラメータに -assecurestring というのがあるんですが、このパラメータを使用すると、ユーザーが入力する文字列が * で表示されます。
-assecurestringを使用すると、変数の型がSystem.Security.SecureStringになります。
System.Security.SecureString型のデータはこのままでは使用できません。
このままでif文などで比較しても正しい結果は得られないので、解読してString型に変換する必要があります。
newpopsさんのblogにその方法が書かれてありましたので参考にさせていただきました。(http://d.hatena.ne.jp/newpops/20050923/p1)
3)System.Data.OracleClientの読み込み
PowerShell起動時はSystem.Data.OracleClientは読み込まれていません。
[reflection.assembly]::LoadWithPartialName で System.Data.OracleClientをロードし、OracleClientクラスを使用可能にしています。
4) DataSetを作成する
取得したデータをXmlへ出力するのに、DataSetのWriteXmlメソッドを使用することにしました。
New-Obejctコマンドレットを使用してDatSetを作成しています。
5)DataAdapterを作成する
これもNew-Objetctコマンドレットを使用しています。
6)XMLへ出力する
4)で述べたとおり、DataSetのWriteXmlメソッドを使用してXMLファイルへの出力を行います。

06.SecureStringから文字列を取得する

Read-Hostコマンドレットのパラメータに -assecurestring というのがあるんですが、このパラメータを使用すると、ユーザーが入力する文字列が * で表示されます。
-assecurestringを使用すると、変数の型がSystem.Security.SecureStringになります。
System.Security.SecureString型のデータはこのままでは使用できません。
このままでif文などで比較しても正しい結果は得られないので、解読してString型に変換する必要があります。
そこで、SecureStringをString型に変換する関数を作成してみました。

Convert-ToStringBSTR.ps1

#===============================================================================
# Convert-ToStringBSTR: SecurityString文字列を解読した値を返す
#
# 使用例
# PS > Convert-ToStringBSTR $SecurityString
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:Convert-ToStringBSTR
{
Param([System.Security.SecureString]$SecureString)
$ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString)
$pass = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($ptr)
return $pass
}
使用方法ですが、まずはこの関数を使用してみるためにSecurityString文字列を作成してみましょう。
Read-Hostコマンドレットで -AsSecureString パラメータを使用すると、コマンドラインで文字列を入力したときに * で表されます。
-AsSecureString を使用すると入力した文字は * で伏せられSecureString型となります。

List1

PS > $pass = Read-Host "パスワードを入力" -AsSecureString
パスワードを入力: ****
次にConvert-ToStringBSTR関数を使用して、List1で作成したSecureString型をString型に変換してみたいと思います。
使用方法は簡単で、関数名の後にSecureStringを指定するだけです。(List2)

List2

PS > Convert-ToStringBSTR $pass
hiro

07.Oracleデータベースからデータを取得してXMLへ保存する GUI版

Oracleデータベースからデータを取得してXMLへ保存する でOracleデータベースからデータを取得し、XMLファイルへ保存する関数を紹介しました。
今回は、これを改善し、
・取得したデータをWinodwsフォームのDataGridViewへの表示
・[XMLへ保存]ボタンが押されたら、ファイル保存ダイアログを表示し、任意の名前を付けて保存
ができるようにしてみました。

Export-OracleDataXml2.ps1

#===============================================================================
# Export-OracleDataXml2: データを取得してXMLファイルへ保存する(Oracle)
#
# 使用例
# PS > Export-OracleDataXml
# PS > DataSource: データソース名
# PS > User ID: ユーザーID
# PS > Password: パスワード
# PS > Query String: クエリ文字列
#
# copyright HIRO's.NET(http://hiros-dot.net.com/)
#===============================================================================
function global:Export-OracleDataXml2
{
#===== 必要情報をユーザーから取得する =====
$DataSource = Read-Host "Data Source"
$UserID = Read-Host "User ID"
$Password = Read-Host "Password" -assecurestring
$QueryString = Read-Host "Query String"
#===== newpopsさんのblog参照 http://d.hatena.ne.jp/newpops/20050923/p1 =====
#SecureStringからパスワード文字列を取得する
$ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password)
$pass = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($ptr)
#===== Oracleからのデータ取得 =====
[reflection.assembly]::LoadWithPartialName("System.Data.OracleClient")
$ConnectionString = "Data Source=" + $DataSource + ";User ID=" + $UserID + ";Password=" + $Pass + ";Integrated Security=no;"
$OraConn = New-Object System.Data.OracleClient.OracleConnection($ConnectionString)
$dtSet = New-Object System.Data.DataSet
$OraDa = New-Object System.Data.OracleClient.OracleDataAdapter($QueryString, $OraConn)
$OraDa.Fill($dtSet)
#===== Formの作成 =====
[reflection.assembly]::LoadWithPartialName("System.Windows.Forms")
$form = New-Object System.Windows.Forms.Form
$form.Text = $DataSource + "@" + $UserID
$form.Width = 500
$form.Height = 400
#===== DataGridViewの作成 =====
$dgvOracle = New-Object System.Windows.Forms.DataGridView
$dgvOracle.Dock = [System.Windows.Forms.DockStyle]::Fill
$dgvOracle.DataSource = $dtSet.Tables[0]
$form.Controls.Add($dgvOracle)
#===== Panelの作成 =====
$panel1 = New-Object System.Windows.Forms.Panel
$form.Controls.Add($panel1)
$panel1.Dock = [System.Windows.Forms.DockStyle]::Bottom
$panel1.Height = 30
#===== [XMLへ保存]ボタンの作成 =====
$btnExport = New-Object System.Windows.Forms.Button
$btnExport.Location = New-Object System.Drawing.Point(324, 4)
$btnExport.Text = "XMLへ保存"
$btnExport.anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Right
$btnExport.Add_Click(
{
#===== ファイル保存ダイアログを作成 =====
$dlgSave = New-Object System.Windows.Forms.SaveFileDialog
$dlgSave.DefaultExt = "XML"
$dlgSave.Filter = "XMLファイル(*.xml)|*.xml"
if ( $dlgSave.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK )
{
#===== データを保存する =====
$dtSet.WriteXml($dlgSave.Filename)
}
})
$panel1.Controls.Add($btnExport)
#===== [閉じる]ボタンの作成 =====
$btnClose = New-Object System.Windows.Forms.Button
$btnClose.Location = New-Object System.Drawing.Point(405, 4)
$btnClose.Text = "閉じる"
$btnClose.anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Right
$btnClose.Add_Click({$form.Close()})
$panel1.Controls.AddRange($btnClose)
#===== Formを表示 =====
$form.ShowDialog()
}
実行結果は下記の通りです。

今回のポイント
・Windows フォームを作成する
VB.NETやC#で開発をされている方は、ソースを見ると何となくわかると思います。

List1

$form = New-Object System.Windows.Forms.Form
でフォームのインスタンスを作成します。
・各コントロールの作成とフォームへの配置
コントロールを作成してフォームへ配置するには

List2

#コントロールの作成
$control = New-Object System.Windows.Forms.コントロール
#コントロールの配置
$form.ControlAdd($control)
#パネルへの配置
$panel1.Controls.Add($btnExport)
ボタンへのクリックイベントは下記のように記述します。

List3

$button.Add_Click({ここに処理したいスクリプトを記述})

08.簡易XMLビューア

簡易XMLビューアを作ってみました。
指定したXMLファイルをGUIで確認することができます。
実行結果は下記の通りです。

View-Xml.ps1

#===============================================================================
# View-Xml: XMLファイルを読み込んで表示する(簡易XMLViewer)
#
# 使用例
# PS > View-Xml XMLファイルパス
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:View-Xml
{
Param($XmlFile)
#パスが指定されているか?
if ( $XmlFile.Length -eq $null )
{
Write-Host "XMLファイルを指定してください"
return
}
#存在するパスか?
if ( -not $(Test-Path $XmlFile) )
{
Write-Host $XmlFile + "は存在しません"
return
}
#データセットを作成し、XMLファイルを読み込む
$dtSet = New-Object System.Data.DataSet
$dtSet.ReadXml($XmlFile)
#===== Formの作成 =====
[reflection.assembly]::LoadWithPartialName("System.Windows.Forms")
$form = New-Object System.Windows.Forms.Form
$form.Text = $XmlFile
$form.Width = 500
$form.Height = 400
#===== DataGridViewの作成 =====
$dgvXML = New-Object System.Windows.Forms.DataGridView
$dgvXML.Dock = [System.Windows.Forms.DockStyle]::Fill
$dgvXML.DataSource = $dtSet.Tables[0]
$form.Controls.Add($dgvXML)
#===== Panelの作成 =====
$panel1 = New-Object System.Windows.Forms.Panel
$form.Controls.Add($panel1)
$panel1.Dock = [System.Windows.Forms.DockStyle]::Bottom
$panel1.Height = 30
#===== [閉じる]ボタンの作成 =====
$btnClose = New-Object System.Windows.Forms.Button
$btnClose.Location = New-Object System.Drawing.Point(405, 4)
$btnClose.Text = "閉じる"
$btnClose.anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Right
$btnClose.Add_Click({$form.Close()})
$panel1.Controls.AddRange($btnClose)
#===== Formを表示 =====
$form.ShowDialog()
}
使用方法は関数名の後に、GUIで確認したいXMLファイルを指定します。

使用例

PS> View-Xml "XMLファイルのパス"
ポイントは
・データセットを作成して、XMLファイルを読み込む
$dtSet = New-Object System.Data.DataSet
$dtSet.ReadXml($XmlFile)
・データセットをDataGridViewに連結する
$dgvXML.DataSource = $dtSet.Tables[0]
・anchorプロパティ
anchorプロパティは -bor 演算子を使うとうまくいきます。(-or演算子は試してみたところダメでした)
-bor はビットごとのOR演算を行います。
です。

09.画像ファイルをリサイズする

昨年(2007年)、デジタル一眼レフを購入したのですが、それをきっかけに息子のスポ少(ミニバス)の写真を撮る機会が増えました。
チームメンバーの方から写真がほしいと言われるので、専用サイトへアップするのですが元画像のままだとサイズが大きすぎるし、枚数は多いしで大変なのです。
ということでリサイズする関数を作ってみました。(jpeg専用です)

Resize-Image.ps1

[void][reflection.assembly]::LoadWithPartialName("System.Drawing")
[void][reflection.assembly]::LoadWithPartialName("System.Drawing.Imaging")
#===============================================================================
# Resize-Image: 画像ファイルをリサイズする(jpegのみ)
#
# パラメータ
# -srcFile : リサイズ元画像ファイルパス
# -dstFile : リサイズ後画像ファイルパス
# -width : リサイズ後の幅
# -height : リサイズ後の高さ
# -quality : 品質
# Default 既定の補間モード
# Low 低品質補間
# High 高品質補間
# NearestNeighbor 最近傍補間
# Bilinear 双一次補間
# Bicubic 双三次補間
# HighQualityBilinear 高品質双一次補間
# HighQualityBicubic 高品質双三次補間
# 使用例
# PS > Resize-Image "C:\Work\AAA.jpg" "C:\Work\BBB.jpg" 600 480 "HighQualityBicubic"
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:Resize-Image
{
Param([string]$srcFile, [string]$dstFile, [int]$width=0, [int]$height=0, [string]$quality="Default")
#元画像ファイルの存在確認
if ( (Test-Path $srcFile) -eq $False )
{
Write-Host "リサイズ元画像が存在しません。パスを確認してください!!"
return
}
#元画像の読み込み
$srcImg = New-Object System.Drawing.Bitmap($srcFile)
$newWidth = 0
$newHeight = 0
#受け取った引数から、新しいサイズを決定する
if ( $width -gt 0 -and $height -eq 0 )
{
$newWidth = $width
$newHeight = $srcImg.Height / ($srcImg.Width / $newWidth)
}
elseif ( $height -gt 0 -and $width -eq 0 )
{
$newHeight = $height
$newWidth = $srcImg.Width / ($srcImg.Height / $newHeight)
}
elseif ( $width -gt 0 -and $height -gt 0 )
{
$newWidth = $width
$newHeight = $height
}
else
{
Write-Host "画像サイズを指定してください"
return
}
$dstImg = New-Object System.Drawing.Bitmap($srcImg, $newWidth, $newHeight)
$g = [System.Drawing.Graphics]::FromImage($dstImg)
#画像品質の設定
switch ($quality)
{
"Default" #既定の補間モード
{$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::Default}
"Low" #低品質補間
{$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::Low}
"High" #高品質補間
{$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::High}
"NearestNeighbor" #最近傍補間
{$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::NearestNeighbor}
"Bilinear" #双一次補間
{$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::Bilinear}
"Bicubic" #双三次補間
{$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::Bicubic}
"HighQualityBilinear" #高品質双一次補間
{$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBilinear}
"HighQualityBicubic" #高品質双三次補間
{$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic}
default
{$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::Default}
}
#リサイズ画像を作成し保存する
$g.DrawImage($srcImg, 0, 0, $newWidth, $newHeight)
$dstImg.Save($dstFile, [System.Drawing.Imaging.ImageFormat]::Jpeg)
#オブジェクトの破棄
$srcImg.Dispose()
$dstImg.Dispose()
}
使用方法は下記の通りです。

使用方法

PS > Resize-Image "リサイズ元画像ファイルのパス" "リサイズ後の画像保存先パス" 幅 高さ 品質
ポイント
1.画像ファイルを扱うので、System.Drawingは必須です。 先頭でアセンブリをロードします。
2.縦横比率を維持する
幅と高さを適切に指定すれば、見た目にもキチンとリサイズされますが、いちいち縦横比を計算してから指定するのは面倒です。 ということで幅または高さのどちらか一方を指定すると、縦横比率を計算したサイズを決定するようにしてあります。
関数内の"#受け取った引数から、新しいサイズを決定する "のコメント以下のif文がその計算を行っている箇所です。
ということでもう1つの使用方法ですが
Resize-Image "リサイズ元画像ファイルのパス" "リサイズ後の画像保存先パス" -width 幅 -quality 品質
または
Resize-Image "リサイズ元画像ファイルのパス" "リサイズ後の画像保存先パス" -height 高さ -quality 品質
のようにします。
これで縦横比が維持された画像が作成されます。
3.画像品質

10.タイピング練習

PowerShellで作ったタイピング練習ソフトです。
このタイピングソフトは、CNNの記事をダウンロードしてきて、その記事から1単語ずつ画面に表示し、ユーザーにその通り入力してもらうというものです。
タイピング速度の速い人は、CNNの最新記事(英語)をちょろっと読めてしまう、一石二鳥のソフトとなっています。
制限時間は60秒1本勝負で(実際には正確に60秒にすることはできませんでした。後述します)、記事カテゴリを選択できるようにしてあります。

Typing.ps1

#===============================================================================
# Typing: CNNの記事(RSS)を利用してタイピング練習する
#
# パラメータ
# なし
# 使用例
# PS > Typing
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:Typing
{
#===============================================
# 初期化処理
#===============================================
#背景色を保存
$bgclr = $host.UI.RawUI.BackgroundColor
#前景色を保存
$fgclr = $host.UI.RawUI.ForegroundColor
#問題の色を定義
$questioncolor = [System.ConsoleColor]::Red
$rss_list = @(
@("Top Stories","http://rss.cnn.com/rss/cnn_topstories.rss"),
@("World", "http://rss.cnn.com/rss/edition_world.rss"),
@("Africa","http://rss.cnn.com/rss/edition_africa.rss"),
@("Americas","http://rss.cnn.com/rss/edition_americas.rss"),
@("Asia","http://rss.cnn.com/rss/edition_asia.rss"),
@("Europe","http://rss.cnn.com/rss/edition_europe.rss"),
@("Middle East","http://rss.cnn.com/rss/edition_meast.rss"),
@("U.S.","http://rss.cnn.com/rss/edition_us.rss"),
@("World Business","http://rss.cnn.com/rss/edition_business.rss"),
@("Technology","http://rss.cnn.com/rss/edition_technology.rss"),
@("Science & Space","http://rss.cnn.com/rss/edition_space.rss"),
@("Entertainment","http://rss.cnn.com/rss/edition_entertainment.rss"),
@("World Sport","http://rss.cnn.com/rss/edition_sport.rss"),
@("Football","http://rss.cnn.com/rss/edition_football.rss"),
@("Travel","http://rss.cnn.com/rss/edition_travel.rss"),
@("Video","http://rss.cnn.com/rss/cnn_freevideo.rss"),
@("Most Recent","http://rss.cnn.com/rss/cnn_latest.rss"),
@("Art of Life Blog","http://rss.cnn.com/rss/edition_artoflife.rss"),
@("Business Traveller Blog","http://rss.cnn.com/rss/edition_richardquest.rss"),
@("In the Field Blog","http://rss.cnn.com/rss/edition_inthefield.rss"),
@("World's Untold Stories Blog","http://rss.cnn.com/rss/edition_untoldstories.rss"),
@("The Screening Room Blog","http://rss.cnn.com/rss/edition_screeningroom.rss"),
@("Marketplace Middle East Blog","http://rss.cnn.com/rss/edition_mme.rss"),
@("Inside the Middle East Blog","http://rss.cnn.com/rss/edition_ime.rss")
)
Write-Host "タイピング練習の問題カテゴリーを選択してください"
for ( $icnt = 0; $icnt -lt $rss_list.Length; $icnt++)
{
Write-Host $($($icnt + 1).ToString("0#") + ": " + $rss_list[$icnt][0])
}
#ユーザーが選択したカテゴリ番号を保存
$no = Read-Host
if ( $([int]$no) -le 0 -and $([int]$no) -gt $rss_list.Length )
{
Write-Host "Noを正しく入力してね"
return
}
Write-Host "データダウンロード中..."
$feed = [xml](new-object system.net.webclient).downloadstring($rss_list[$no - 1][1])
$contents =$($feed.rss.channel.item | Select-Object -property DESCRIPTION)
Write-Host "データダウンロード完了"
foreach ( $content in $contents )
{
$a += $content.Description.split(" ")
}
Write-Host "[Enter]キーを押すと始まります"
Read-Host
$start = Get-Date
$i = 0
$score = 0
$miss = 0
#背景色を黒にする
$host.UI.RawUI.BackgroundColor = [System.ConsoleColor]::Black
cls
while ( $(Get-Date).subtract($start).TotalSeconds -lt 60)
{
#問題を出す
if ( $a[$i] -ne " ")
{
Write-Host $a[$i] -foregroundcolor $questioncolor
#ユーザーからの回答入力を取得する
$Host.UI.RawUI.ForegroundColor = $fgclr
$input = Read-Host
cls
#正解したらスコアをカウントアップ
if ( $input -ceq $a[$i] )
{
$score += 10
}
else
{
$miss++;
Write-Host "`a"
cls
}
}
$i++
#問題がなくなったら終了
if ($a.Length -eq $i )
{
break;
}
}
Write-Host $("start: " + $start)
Write-Host $("end: " + $(Get-Date))
Write-Host $("Score: " + $Score)
Write-Host $("Miss:" + $miss)
}
ポイント
1.背景色と前景色

PowerShellのコンソールウィンドウの背景色や前景色は $host.UI.RawUI のBackgroundColor と ForegroundColor を指定することで変更できます。
色はSystem.ConsoleColor列挙体を指定します。
2.問題の色
出題する問題(単語)の色は Write-Hostコマンドレットの-foregroundcolor パラメータで指定しています。
3.カテゴリを選択させる

カテゴリはあらかじめ変数として持っておくこととしました。($rss_list) このとき変数は2次元配列変数にし、カテゴリ名とRSSのURLをペアで持たせています。
$rss_list[0][1]とするとURL http://rss.cnn.com/rss/cnn_topstories.rss が取り出せるという寸法です。
で、ユーザーにカテゴリを入力させるわけですが、Read-Hostコマンドレットを使用することで入力を取得することができます。
4.rssのダウンロード
rssのダウンロードはsystem.net.webclientのdownloadstringメソッドを使用しています。
[xml](new-object system.net.webclient).downloadstring($rss_list[$no - 1][1]) の部分です。
先頭に[xml]と付けることでxmlにキャストしています。
5.descriptionタグ内容の取り出し
$contents =$($feed.rss.channel.item | Select-Object -property DESCRIPTION)
で行っています。 Select-Object でDescriptionを取り出します。
6.制限時間
whileでループして60秒経過したら終わるようにしています。
while ( $(Get-Date).subtract($start).TotalSeconds -lt 60)
{
}
ただし、このタイピングソフトは正確には60秒を計測することはできません。
なぜなら、Whileの中でRead-Hostコマンドレットを使用しているからです。
Read-Hostコマンドレットはユーザーが[Enter]を押すまで処理を止めてしまいます。よって60秒経過してもユーザーが何も入力しなければ、このループは1時間経過しようが止まらないのです。 だれか良い方法知っていたら教えてください。 Read-Keyみたいなコマンドレット作れば良いのかしら?
7.入力ミスをしたらBeepを鳴らす
Beep音はWrite-Host "`a" と書けば鳴らすことができます。

11.IPアドレスからホスト名を取得する

PowerShellでIPアドレスからホスト名を取得する関数を作ってみました。
IPアドレスからホスト名を取得するのに、System.Net.DnsのGetHostEntryメソッドを使用しています。
HostEntry情報を取得したら、その中のHostNameプロパティを参照し、ホスト名を取得します。

Get-HostByName.ps1

#===============================================================================
# Get-HostByName: IPアドレスからホスト名を取得する
#
# 使用例
# PS > Get-HostByName 10.84.5.10
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
[void][reflection.assembly]::LoadWithPartialName("System.Net")
function global:Get-HostByName
{
Param ([string]$IPAddress)
$hostEntry = New-Object System.Net.IPHostEntry
$hostEntry = [System.Net.Dns]::GetHostEntry($IPAddress)
return $hostEntry.HostName
}
使用方法は下記の通りで、関数名の後にIPアドレスを指定します。

使用例

PS > Get-HostByName 203.216.227.176
f1.top.vip.tnz.yahoo.co.jp

12.ホスト名からIPアドレスを取得する

ホスト名からIPアドレスを取得する関数です。
System.Net.DnsのGetHostEntryメソッドを使用しています。
HostEntry情報を取得したら、その中のAddressList(配列で返されます)を取得し、IPAddressToString でIPアドレスのみを取得しています。

Get-HostByAddress.ps1

#===============================================================================
# Get-HostByAddress: ホスト名からIPアドレスを取得する
#
# 使用例
# PS > Get-HostByAddress "www.yahoo.co.jp"
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
[void][reflection.assembly]::LoadWithPartialName("System.Net")
function global:Get-HostByAddress
{
Param ([string]$HostName)
$hostEntry = New-Object System.Net.IPHostEntry
$hostEntry = [System.Net.Dns]::GetHostEntry($HostName)
return $hostEntry.AddressList[0].IPAddressToString
}
使用方法は下記の通りで、関数名の後にホスト名を指定します。

使用例

PS > Get-HostByAddress www.yahoo.co.jp
203.216.227.176

13.指定した年月の第1日曜日を取得する

指定した年月の第1日曜日を取得する関数を作成しました。

Get-FirstSunday.ps1

#===============================================================================
# Get-FirstSunday: 指定した年月の第1日曜日を取得する
#
# パラメータ:
# $Year: 年(省略した場合は現在の年)
# $Month: 月(省略した場合は現在の月)
#
# 使用例1(年月指定)
# PS > Get-FirstSunday 2008 2
#
# 使用例2(年月省略)
# PS > Get-FirstSunday
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:Get-FirstSunday
{
Param ([int]$Year = $(Get-Date).Year, [int]$Month = $(Get-Date).Month)
for ( $i = 0; $i -lt 7; $i++ )
{
$checkDay = New-Object DateTime($Year, $Month, [int]($i + 1))
if ( $checkDay.DayOfWeek -eq 0 )
{
break
}
}
return $i + 1
}
使用方法は、List1の様に 関数名[Enter] と入力すると、当月の第一日曜日の日を返します。
2008/05/03にこの関数を実行すると、第一日曜日は5/4なので"4"を返します。

List1

PS > Get-FirstSunday
4
List2のように Get-irstSunday 年 月[Enter] と入力した場合は 2008年6月の第1日曜日である"1"を返します。

List2

PS > Get-FirstSunday 2008 6
1
開発ポイントですが、この関数は DateTime 構造体の DayOfWeek メソッドを使用し、指定した年月の1~7までのどれが日曜日かを判定して返します。

14.指定した年月の最終日を取得する

指定した年月の最終日を取得する関数を作成してみました。

Get-LastDay.ps1

#===============================================================================
# Get-LastDay: 指定した年月の最終日を取得する
#
# パラメータ:
# $Year: 年(省略した場合は現在の年)
# $Month: 月(省略した場合は現在の月)
#
# 使用例1(年月指定)
# PS > Get-LastDay 2008 2
#
# 使用例2(年月省略)
# PS > Get-LastDay
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:Get-LastDay
{
Param ([int]$Year = $(Get-Date).Year, [int]$Month = $(Get-Date).Month)
return [System.DateTime]::DaysInMonth($Year, $Month)
}
関数の使用方法ですが、Get-LastDay[Enter] と入力すると当月の最終日を返します。
2008/05/03にこの関数を実行すると、"31"を返します。

List1

PS > Get-LastDay
31
下記のように、Get-LastDay 年 月[Enter] とした場合は指定した年月の最終日を返します。

List2

PS > Get-LastDay 2008 6
30
ポイントですが、この関数はDateTime構造体のDaysInMonthメソッドを利用して最終日を取得しています。

15.指定した年月のカレンダーを表示する CUI版 その1

PowerShellでカレンダーを表示する関数を作成しました。
この関数を実行するには、 指定した年月の第1日曜日を取得する 指定した年月の最終日を取得する が必要です。

Get-Calendar.ps1

#===============================================================================
# Get-Calendar: 指定した年月のカレンダーを表示する
#
# パラメータ:
# $Year: 年(省略した場合は現在の年)
# $Month: 月(省略した場合は現在の月)
#
# 使用例1(年月指定)
# PS > Get-Calendar 2008 2
#
# 使用例2(年月省略)
# PS > Get-Calendar
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:Get-Calendar
{
Param ([int]$Year = $(Get-Date).Year, [int]$Month = $(Get-Date).Month)
#表示用年月作成
$DispMonth = New-Object DateTime($Year, $Month, 1)
$strDispMonth = ($DispMonth.ToString("MMMM",[System.Globalization.CultureInfo]'en-US') + " " + $Year)
#横幅35文字の中間に表示されるようにする
Write-Host ""
Write-Host $strDispMonth.PadLeft([int](35 - (35 - $strDispMonth.Length) / 2))
$firstSunday = Get-FirstSunday $Year $Month
$lastDay = Get-LastDay $Year $Month
Write-Host "Sun. Mon. Tue. Wed. Thu. Fri. Sat."
# 第1日曜日が"1日"以外の第1週を表示
if ( $firstSunday -ne 1 )
{
for ( $i = 1; $i -lt $firstSunday; $i++ )
{
$week += $i.ToString(" # ");
}
$spc = " "
$spc *= [int](7 - ( $firstSunday - 1 ))
Write-Host ($spc + $week)
}
#中間週を表示
$loopWeek = [Math]::floor(($LastDay - $firstSunday) / 7)
$Day = $firstSunday
for ( $weekCnt = 0; $weekCnt -lt $loopWeek; $weekCnt++ )
{
$week = "";
for ( $iDay = 0; $iDay -lt 7; $iDay++ )
{
if ( $Day -lt 10 ) { $week += $Day.ToString(" # "); }
else { $week += $Day.ToString(" ## "); }
$Day += 1
}
Write-Host ($week)
}
#最終週を表示
if ( $Day -le $LastDay )
{
$week = ""
for ( $iDay = $Day; $iDay -le $LastDay; $iDay++ )
{
$week += $Day.ToString(" ## ");
$Day += 1
}
Write-Host ($week)
}
}
実行例は下記の通りです。

使用方法ですが、 Get-Calendar[Enter]と入力すると、当月のカレンダーを表示します。

List1

PS > Get-Calendar
May 2008
Sun. Mon. Tue. Wed. Thu. Fri. Sat.
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
指定した年月のカレンダーを表示するには、Get-Calendar 年 月[Enter] と入力します。

List2

PS > Get-Calendar 2008 6
June 2008
Sun. Mon. Tue. Wed. Thu. Fri. Sat.
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
ポイント

1.タイトル(年月)の表示

「月」を英語で表示したかったので、ToString("MMMM")としましたが、”2月”と返ってくるので
ToString("MMMM",[System.Globalization.CultureInfo]'en-US') として英語で取得しています。
カレンダーを表示するのに必要な幅は35文字としています。
これは1日を5文字使用して表示しているので、× 7日 = 35文字となっています。
でタイトルは中心に表示したいので、計算して左側にスペースを入れています。(PadLeftメソッド)
2.カレンダーの表示
表示は第1週、中間週、最終週の3つに分けて行っています。
これは、第1週が必ずしも日曜日から始まるとは限らないこと、最終週が必ずしも土曜日で終わるとは限らないことを考慮したためです。

16.指定した年月のカレンダーを表示する CUI版 その2

指定した年月のカレンダーを表示する CUI版 その1 を少し改造して、土曜日を水色で、日曜日を赤で表示するようにしてみました。

関数は下記の通りです。

Get-Calendar2.ps1

#===============================================================================
# Get-Calendar2: 指定した年月のカレンダーを表示する(色つき版)
#
# パラメータ:
# $Year: 年(省略した場合は現在の年)
# $Month: 月(省略した場合は現在の月)
#
# 使用例1(年月指定)
# PS > Get-Calendar2 2008 2
#
# 使用例2(年月省略)
# PS > Get-Calendar
#
# copyright HIRO's.NET(http://hiros-dot.net//)
#===============================================================================
function global:Get-Calendar2
{
Param ([int]$Year = $(Get-Date).Year, [int]$Month = $(Get-Date).Month)
#表示用年月作成
$DispMonth = New-Object DateTime($Year, $Month, 1)
$strDispMonth = ($DispMonth.ToString("MMMM",[System.Globalization.CultureInfo]'en-US') + " " + $Year)
#横幅35文字の中間に表示されるようにする
Write-Host ""
Write-Host $strDispMonth.PadLeft([int](35 - (35 - $strDispMonth.Length) / 2))
$firstSunday = Get-FirstSunday $Year $Month
$lastDay = Get-LastDay $Year $Month
Write-Host "Sun." -foregroundcolor Red -noNewline
Write-Host " Mon. Tue. Wed. Thu. Fri. " -noNewline
Write-Host "Sat." -foregroundcolor Cyan
# 第1日曜日が"1日"以外の第1週を表示
if ( $firstSunday -ne 1 )
{
for ( $i = 1; $i -lt $firstSunday - 1; $i++ )
{
$week += $i.ToString(" # ")
}
$spc = " "
$spc *= [int](7 - ( $firstSunday - 1 ))
Write-Host ($spc + $week) -noNewline
#土曜日をCyanにする
Write-Host ($firstSunday - 1).ToString(" # ") -foregroundcolor Cyan
}
#中間週を表示
$loopWeek = [Math]::floor(($LastDay - $firstSunday) / 7)
$Day = $firstSunday
for ( $weekCnt = 0; $weekCnt -lt $loopWeek; $weekCnt++ )
{
for ( $iDay = 0; $iDay -lt 7; $iDay++ )
{
if ( $Day -lt 10 ) { $strDay = $Day.ToString(" # ") }
else { $strDay = $Day.ToString(" ## ") }
#日曜日はRed, 土曜日はCyanにする
if ($iDay -eq 0 ) { Write-Host $strDay -foregroundcolor Red -noNewline }
elseif ($iDay -eq 6 ) { Write-Host $strDay -foregroundcolor Cyan}
else { Write-Host $strDay -noNewline }
$Day += 1
}
#Write-Host ($week)
}
#最終週を表示
if ( $Day -le $LastDay )
{
$week = ""
$LastSunday = $Day
$Day += 1
for ( $iDay = $Day; $iDay -le $LastDay - 1; $iDay++ )
{
$week += $Day.ToString(" ## ")
$Day += 1
}
#最終週の日曜日の色をRedにする
Write-Host $LastSunday.ToString(" ## ") -foregroundcolor Red -noNewline
Write-Host $week -noNewline
#最終日が土曜日の場合は色をCyanにする
if ($LastDay - $LastSunday -eq 6) { Write-Host $LastDay.ToString(" ## ") -foregroundcolor Cyan }
else { Write-Host $LastDay.ToString(" ## ") }
}
}
使用方法は、
Get-Calendar2[Enter]
と入力するか
Get-Calendar2 年 月[Enter]
とします。
ポイントは
Write-Hostコマンドレットで色を付けているということです。
前景色(文字色)はパラメータ -foregroundcolor で指定することができます。
指定可能な色は
* Black
* DarkBlue
* DarkGreen
* DarkCyan
* DarkRed
* DarkMagenta
* DarkYellow
* Gray
* DarkGray
* Blue
* Green
* Cyan
* Red
* Magenta
* Yellow
* White
です。
あとは むたぐちさん に Write-Hostコマンドレットは、-noNewlineパラメータを使用すれば改行しないで文字を出力できることを教えていただきましたので、それを使用しました。

17.指定した年月のカレンダーを表示する GUI版

Windows Formにカレンダーを表示する関数を作成しました。
実行結果は下記の通りです。

View-Calendar.ps1

[void][reflection.assembly]::LoadWithPartialName("System.Windows.Forms")
#===============================================================================
# View-Calendar: 指定した年月のカレンダーを表示する(GUI版)
#
# パラメータ:
# $Year: 年(省略した場合は現在の年)
# $Month: 月(省略した場合は現在の月)
#
# 使用例1(年月指定)
# PS > View-Calendar 2008 2
#
# 使用例2(年月省略)
# PS > View-Calendar
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:View-Calendar
{
Param ([int]$Year = $(Get-Date).Year, [int]$Month = $(Get-Date).Month)
#===== Formの作成 =====
$form = New-Object System.Windows.Forms.Form
$form.Text = "Calendar"
$form.Width = 147
$form.Height = 210
$form.FormBorderStyle = [Windows.Forms.FormBorderStyle]::FixedToolWindow
#===== MonthCalendarの作成 =====
$cal = New-Object System.Windows.Forms.MonthCalendar
$cal.Dock = [System.Windows.Forms.DockStyle]::Fill
$cal.SelectionStart = New-Object DateTime($Year, $Month, 1)
$cal.SelectionEnd = New-Object DateTime($Year, $Month, 1)
$form.Controls.Add($cal)
#===== Panelの作成 =====
$panel1 = New-Object System.Windows.Forms.Panel
$form.Controls.Add($panel1)
$panel1.Dock = [System.Windows.Forms.DockStyle]::Bottom
$panel1.Height = 30
#===== [閉じる]ボタンの作成 =====
$btnClose = New-Object System.Windows.Forms.Button
$btnClose.Location = New-Object System.Drawing.Point(61, 4)
$btnClose.Text = "閉じる"
$btnClose.anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Right
$btnClose.Add_Click({$form.Close()})
$panel1.Controls.Add($btnClose)
[void]$form.ShowDialog()
}
使用方法は
View-Calendar[Enter]
と入力すれば、当月のカレンダーを
View-Calendar 年 月[Enter]
と入力すれば、指定年月のカレンダーを表示します。

List1

PS > View-Calendar
PS > View-Calendar 2008 6
ポイント

見てのとおり、今回はMonthCalendarコントロールを使用しました。
MonthCalendarコントロールは、日にちをマウスで選択可能なので、フォームが閉じられる時に選択されている日を返すようにしてもよいかもしれませんね。
その場合は
[閉じる]ボタンが押される時の処理を

List2

$btnClose.Add_Click({$form.Close()})
から

List3

$btnClose.Add_Click({$form.DialogResult = "OK"; $form.Close()})
として、フォームのShowDialog()をList4のようにすればよいと思います。

List4

if ( $form.ShowDialog() -eq "OK" )
{
retrurn $cal.SelectionStart.ToString()
}

18.サービスのステータスごとに色をつける

Get-Serviceコマンドレットは、ローカル コンピュータ上のサービスを取得するコマンドレットです。
このコマンドレットの実行結果には、サービスのステータス情報("Stopped"か"Running")が含まれています。
"Stopeed"だったら文字色を赤で、"Running"だったらシアンでサービス名を表示する関数を作ってみました。
実行結果は下図のとおりです。

Color-SrvStatus.ps1

#===============================================================================
# Color-SrvStatus: サービスのステータス別に色を付ける
#
# 使用例
# PS > Color-SrvStatus
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:Color-SrvStatus
{
#サービスを取得
$srv = get-service
#カウンタの初期化
$iCnt = 0
for ( $iCnt = 0; $iCnt -lt $srv.length; $iCnt++ )
{
#各サービスのステータスを判断して色を付ける
if ($srv[$iCnt].status -eq "running")
{write-host $srv[$iCnt].Name -foregroundcolor "cyan"}
elseif ($srv[$iCnt].status -eq "stopped")
{write-host $srv[$iCnt].Name -foregroundcolor "red"}
else
{write-host $srv[$iCnt].Name}
$iCnt++
}
}
使用方法は、List1のように関数名を入力するだけです。

ポイント

といっても、なんのことはありません。
取得結果のStatusを判断して、色を付けています。
この関数はサービス名しか表示しないので、用途に合わせて表示される情報を増やすことをおすすめします。

List1

PS > Color-SrvStatus

19.複数行の入力を取得する

PowerShellでは複数行の入力を読み取るコマンドレットがありません。
そこでコマンドラインから複数行の入力を取得する関数を作成しました。
下記が、複数行の入力を受け取るRead-MultiLine関数です。

Read-MultiLine.ps1

#=========================================================================================
# Read-MultiLine: コマンドラインから複数行の入力を受け取る
#
# UPDATE 2008/04/24 Ver.1.0.0
# 2008/05/01 Ver.1.0.1 終了判定文字に1文字以上の文字列を指定できるよう修正
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#=========================================================================================
function global:Read-MultiLine ( [string]$prompt, [string]$endChar = ";" ){
if ($args[0] -eq "-?" )
{
Write-Host @"
名前:
Read-MultiLine
概要:
コマンドラインから複数行文字列を取得します。
構文:
Read-MultiLine [-prompt] [-endChar]
使用方法:
-------------------------- 例 1 --------------------------
`$a = Read-MultiLine
この例はコマンドラインから複数行を取得し行終端が";"の場合に読み取りを中止し結果を返します。
入力の終了を判定する文字は";"が規定値です。
-------------------------- 例 2 --------------------------
`$a = Read-MultiLine -prompt "文字列を入力してください"
この例はプロンプトに"文字列を入力してください"と表示した後に入力を受け付けます。
-------------------------- 例 3 --------------------------
`$a = Read-MultiLine -endChar "#"
この例は入力の終了を判定する文字を"#"とします。
ユーザー入力の行終端が"#"である場合に、入力を中断し結果を返します
-------------------------- 例 4 --------------------------
`$a = Read-MultiLine -endChar "EOF"
この例は入力の終了を判定する文字を"EOF"とします。
ユーザー入力の行終端が"EOF"である場合に、入力を中断し結果を返します
"@ -foregroundcolor Cyan
return
}
if ( $prompt.Length -gt 0 ){ Write-Host ($prompt + ":") }
while(1)
{
$ip += Read-Host
if ($ip.SubString($ip.Length - $endChar.Length) -eq $endChar){ break; }
else{$ip += "`n"}
}
#Write-Host $ip
return $ip.Substring(0, $ip.Length - $endChar.Length)
}
この関数は、実行すると";"が入力されるまで、複数行に渡る文字列の読み取りを行います。

List1

PS > $inp = Read-MultiLine
ABC
DEF
GHI;
下記のようにするとプロンプトを表示した後に入力を受けつけます。

List2

PS > $inp = Read-MultiLine "入力してください"
入力してください:
This
is
Read-MultiLine
Command;
また、下記のようにすると終了判定文字を";"から"#"に変更することができます。

List3

PS > $inp = Read-MultiLine -endChar "#"
ABC
DEF
GHI#

20.ログを残す

スクリプトや関数のデバッグで、途中経過をテキストファイルに書き込みたくて Write-Log という関数を作成しました。

Write-Log.ps1

#===============================================================================
# Write-Log: ログを作成する
#
# 使用例1:
# PS > Write-Log "ログを残します"
# 使用例2:
# PS > Write-Log "ログを残します", "C:\Work\Error.log"
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:Write-Log
{
Param ( [String]$msg, [String]$LogFile="C:\Work\History.log" )
$write_msg = ((Get-Date).ToString() + "`t" + $msg)
Add-Content -Path $LogFile -Value $write_msg
}
書式は
Write-Log "ログメッセージ" "保存ファイル名"
です。
使用方法は簡単で、List1の様に入力すると
C:\Log.txtというファイルが作成され、ログを書き込んだ時間とメッセージが書き込まれます。

List1

PS > Write-Log "ログメッセージ" "C:\Log.txt"
List1によって作成されるファイルの例を下記に示します。

C:\Log.txt

2008/05/05 19:19:32 ログメッセージ
開発ポイントですが、ファイルへの書き込みにAdd-Contentコマンドレットを使用しています。
Add-Contentコマンドレットは、すでにファイルが存在する場合には追記書き込みを行います。
これにより、前のメッセージを残しながらログを作成していくことを可能にしています。

01.SQL*PLUSもどきを作る その1

自分が勤務している会社は、データベースがOracleなのでSQL*PLUSをよく使用します。
SQL*PLUSってCMD.EXEやPowerShellからでも
C:\Work> sqlplus
って入力すれば使用できますよね?
で、最近はCMD.EXEよりはPowerShellを使用しているので、PowerShellからSQL*PLUSを呼び出しています。
sqlplus[Enter]と入力して sqlplusを使用するとPowerShellのコマンドレットが使えなくなります。(sqlplusを起動させているので当然なのですが)
自分は欲張りなので、SQL*PLUSを起動しつつもPowerShellも使いたいと思いました。そうすれば取得結果をリダイレクトしてファイルに落としたり、Window Formへデータ渡してみたりといろいろと応用が利きそうです。
ということで、PowerShellで動くSQL*PLUSもどきを作ってみたいと思います。
とはいっても、descコマンドと、SQLの実行ができることだけを目標にしています。
今回は、SQL*PLUSもどきの入り口部分を作ってみました。
関数名はPSOracle(PowerShell で Oracleの略)です。
実行すると、ユーザー名、パスワード、接続先を聞かれるので、順に入力すると、
1.PSOracle用のその他のライブラリ(関数ファイル)をPowerShellへ登録
2. グローバル変数へ接続先情報の登録
3.実際に接続してOracleサーバーのバージョンの表示を行います
以下が関数本体(PSOracle.ps1)です。

PSOracle.ps1

#===============================================================================
# Get-OracleConnectionString: PowerShellで独自のOracle関連スクリプトを使用可能にする
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
#Assemblyのロード
[void][reflection.assembly]::LoadWithPartialName("System.Data.OracleClient")
function Global:PSOracle
{
if ($args[0] -eq "-?")
{
Write-Host @"
名前:
PSOracle
概要:
PowerShellで独自のOracle関連スクリプトを使用可能にします
構文:
PSOracle
使用方法:
PS > PSOracle
ユーザー名を入力してください: USERNAME
パスワードを入力してください: PASSWORD
接続先を入力してください: OracleServer
"@ -foregroundcolor Cyan
return
}
#Oracle専用スクリプトファイルを格納しているディレクトリの設定
$OracleScriptPath = $([Environment]::GetFolderPath(`"MyDocuments`"))\WindowsPowerShell\Oracle"
#存在するパス?
if ( Test-Path $OracleScriptPath )
{
#呼び出し演算子(&)を使用して関数を登録
Get-ChildItem $OracleScriptPath -Include "*.ps1" -Recurse -Force | % { &($_.Fullname); }
}
else
{
#実行可能なスクリプトがない場合は処理終了
return
}
#ユーザーから接続先情報を取得する
$UserID = Read-Host "ユーザー名を入力してください"
$Password = Read-Host "パスワードを入力してください" -assecurestring
$DataSource = Read-Host "接続先を入力してください"
#変数の作成
Set-Variable -Scope "Global" -Name "OracleDataSource" -value $DataSource
Set-Variable -Scope "Global" -Name "OracleUserID" -Value $UserID;
Set-Variable -Scope "Global" -Name "OraclePassword" -Value $Password;
Set-Variable -Scope "Global" -Name "OracleConnInfo" -Value "$UserID@$DataSource";
$strSQL = "SELECT PRODUCT || 'Release ' || VERSION FROM product_component_version Where UPPER(PRODUCT) LIKE 'ORACLE%'"
$ConnectionString = (Get-OracleConnectionString $UserID $Password $DataSource)
$OraConn = New-Object System.Data.OracleClient.OracleConnection($ConnectionString)
$dtSet = New-Object System.Data.DataSet
$OraDa = New-Object System.Data.OracleClient.OracleDataAdapter($strSQL, $OraConn)
[void]$OraDa.Fill($dtSet)
if ( $dtSet.Tables.Count -gt 0 )
{
Write-Host ("`n" + $dtSet.Tables[0].Rows[0][0].ToString() + " - Production`n")
}
trap [System.Data.OracleClient.OracleException]
{
Write-Error ("接続に失敗しました。")
break;
}
trap
{
Write-Error ($Error[0].Exception);
break;
}
}
使用方法ですが、コマンドラインでList1のように PSOracle[Enter]と入力します。

List1

PS > PSOracle
すると「ユーザー名「パスワード」「接続先」を聞かれるので順に入力します。(List2)
うまく接続ができると、接続先のサーバーのバージョンが表示されます。

List2

ユーザー名を入力してください: scott
パスワードを入力してください: *****
接続先を入力してください: server01
Oracle 8i Release 8.1.7.1.1 -Production
使用方法を参照するにはList3ように入力します。

List3

PS > PSOracle -?
ポイント
1.PSOracle用ライブラリの読み込み
PSOracle関数を呼び出すと、最初にMy Documents\WindowsPowerShell\Oracle フォルダ内にある*.ps1ファイルを読み込み、PowerShellに関数を登録します。
こうすることで、PSOracleが実行されたときに、必要な関数を登録します。
SQL*PLUSもどきで必要な関数を*.ps1ファイル化して、このフォルダに置くことで、PSOracleを拡張していくことを可能にしてます。
動的にPowerShellに関数を登録するには呼び出し演算子(&)を使用して登録しています。
2.ユーザーからの情報取得

ユーザーから情報を取得するにはRead-Hostコマンドレットを使用します。
パスワードに関しては、入力した文字が丸見えでは困るので -assecurestring パラメータを付加しています。こうすることで入力した文字は*で表示されます。
3.グローバル変数の作成
PSOracleの関数を抜けてしまうと、ユーザーから取得した接続先情報が失われてしまうのでグローバル変数に登録します。
グローバル変数の作成は Set-Variableコマンドレットを使用して -Scopeパラメータで"Global"を使用します。
ここで作成した変数に、ユーザーから取得した情報をセットすることで、関数を抜けた後でも再利用できるようにしています。
4.Oracleへ接続する
Oracleへの接続はOracleClientを使用しています。
PSOracleが読み込まれたときに、System.Data.OracleClientをロードして使用可能にしています。
接続文字列は、自作関数 Get-OracleConnectionString(次回説明予定)で作成しています。この接続情報を元にOracleへ接続してサーバ情報を取得するSQL文を実行しデータセットへ結果を取得します。
5.エラートラップ

接続時のエラートラップは trap {} で行います。
これはVB.NETやC#でいうところのcatchの部分に相当します。 VB.NETやC#を扱っているとtry部分がないのが気になるところです。 関数内で例外が発生すると trap 部分が処理されます。

02.SQL*PLUSもどきを作る その2

SQL*PLUSもどきを作る その1 の続きです。
接続文字列を作成する関数 Get-OracleConnectionStirng関数を紹介します。

Get-OracleConnectionStirng.ps1

#================================================================================================
# Get-OracleConnectionString: Oracle用接続文字列を作成する
#
# UPDATE: 2008-04-25 Ver.1.0.0
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#================================================================================================
function global:Get-OracleConnectionString([string]$UserID, [object]$Password, [string]$DataSource)
{
if ($args[0] -eq "-?")
{
Write-Host @"
名前:
Get-OracleConnectionString
概要:
Oracle用接続文字列を作成します
構文:
Get-OracleConnectionString [-UserID] [-Password] [-DataSource]
使用方法:
`$ConnString = (Get-OracleConnectString "User" "Password" "ServerName")
"@ -foregroundcolor Cyan
return
}
#パスワードがSecureString型の場合はString型にする
if ( $Password -is [System.Security.SecureString] )
{
$ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password)
$pass = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($ptr);
}
else
{
$pass = $Password
}
#接続文字列を作成して返す
return "Data Source=$DataSource;User ID=$UserID;Password=$pass;Integrated Security=no;"
}
使用方法はList1の通りで
Get-OracleConnectionString ユーザー名 パスワード 接続先{Enter]
と入力します。
この接続文字列はOracleClient用のものが作成されます。
また引数の「パスワード」ですが、これにはString型またはSecureString型を渡します。
SecureString型が渡された場合は、関数内部でString型に戻して接続文字列を作成します。
*で伏せられたパスワード文字列も、この関数を通して接続文字列を返すと、上パスワードが丸見えになりますので使用する場合は注意してください。
今回紹介した関数は SQL*PLUSもどきを作る その1 の中で使用していますので、興味がある方は参考にしてみてください。

List1

PS > Get-OracleConnectionString scott tiger OraSvr10g
Data Source=OraSvr10g;User ID=scott;Password=tiger;Integrated Security=no;

03.SQL*PLUSもどきを作る その3

SQL*PLUSもどきを作る その1
SQL*PLUSもどきを作る その2
の続きです。
Select文を実行して、取得した結果をDataSetで返す関数を紹介します。

Execute-QueryString.ps1

#=========================================================================================
# Execute-QueryString: QueryStringを実行し結果をデータセットで返す
#
# UPDATE: 2008-04-27 Ver.1.0.0
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#=========================================================================================
function global:Execute-QueryString
{
Param ( [string]$QueryString )
#接続文字列の作成
$ConnectionString = (Get-OracleConnectionString $OracleUserID $OraclePassword $OracleDataSource)
#OracleConnectionの作成
$OraConn = New-Object System.Data.OracleClient.OracleConnection($ConnectionString)
#データセットの作成
$dtSet = New-Object System.Data.DataSet
#QueryStringを実行しデータを取得
$OraDa = New-Object System.Data.OracleClient.OracleDataAdapter($QueryString, $OraConn)
[void]$OraDa.Fill($dtSet)
return $dtSet
}
この関数は SQL*PLUSもどきを作る その2 で説明したGet-OracleConnectionString関数を使用して接続文字列を作成し、Oracleへ接続します。
このときの引数に与えているのは SQL*PLUSもどきを作る その1 のPSOracle関数内で作成されたグローバル変数です。
OracleDataAdapterを使用して、QueryStringを実行し結果をDataSetへ格納します。

04.SQL*PLUSもどきを作る その4

SQL*PLUSもどきを作る その1
SQL*PLUSもどきを作る その2
SQL*PLUSもどきを作る その3
の続きです。
SQL*PLUSのdescコマンドです。
describeコマンドを表現する関数を下記のように作ってみました。

desc.ps1

#================================================================================================
# desc: Oracleのdescコマンド
#
# UPDATE: 2008-04-28 Ver.1.0.0
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#================================================================================================
function global:desc ([string]$TABLE_NAME) {
$TBL = $TABLE_NAME.ToUpper()
#descコマンドを実現させるためのSQL文作成
$QueryString = "SELECT "
$QueryString += "COLUMN_ID,"
$QueryString += "COLUMN_NAME,"
$QueryString += "DECODE(NULLABLE,'N','NOT NULL') NULLABLE,"
$QueryString += "DATA_TYPE || '(' || "
$QueryString += "DECODE(DATA_PRECISION, NULL, TO_CHAR(DATA_LENGTH),"
$QueryString += "DECODE(DATA_SCALE,0,"
$QueryString += "TO_CHAR(DATA_PRECISION),"
$QueryString += "TO_CHAR(DATA_PRECISION) || ',' || TO_CHAR(DATA_SCALE))) || ')' DATATYPE "
$QueryString += "FROM "
$QueryString += "ALL_TAB_COLUMNS WHERE TABLE_NAME = '$TBL' ORDER BY COLUMN_ID"
#DataSetに取得する
$dtSet = (Execute-QueryString $QueryString)
if ( $dtSet.Tables.Count -gt 0 )
{
#format-tableコマンドレットでデータを表示
$dtSet.Tables[0].Rows | format-table
}
}
使用方法はSQL*PLUSのdescコマンドと一緒で desc テーブル名/ビュー名 とします。

List1

PS > desc emp
COLUMN_ID COLUMN_NAME NULLABLE DATATYPE
--------- ----------- -------- --------
1 EMPNO NOT NULL NUMBER(4)
2 ENAME VARCHAR2(10)
3 JOB VARCHAR2(9)
4 MGR NUMBER(4)
5 HIREDATE DATE(7)
6 SAL NUMBER(7,2)
7 COMM NUMBER(7,2)
8 DEPTNO NUMBER(2)
一応 More コマンドも使用可能で

List2

PS > desc emp | more
と入力して1ページずつの表示も可能です。
リダイレクトも可能で

List3

PS > desc emp > C:\Work\emp.txt
のようにすると 出力結果をC:\Work\emp.txtに作成します。
開発ポイントですが
descコマンドを実現するために、情報を ALL_TAB_COLUMNS から取得する。
結果の出力にformat-tableコマンドレットを使用する。
といったところでしょうか。出力をどうするかかなり悩みました。DataReaderで1行ずつ取得するとテキストの整形(列ごとにきれいに表示させる)処理を書く必要が出てくるためどうしたものかと考えていましたが、パイプでformat-tableコマンドレットへデータを渡したところきれいに表示されました。
見ていただけばわかるように、データセットにあるテーブルの行を丸投げしているだけです。
PowerShellってこういうところが非常によくできていますね。改めてすばらしいツールだと思いました。

05.SQL*PLUSもどきを作る その5

SQL*PLUSもどきを作る その1
SQL*PLUSもどきを作る その2
SQL*PLUSもどきを作る その3
SQL*PLUSもどきを作る その4
の続きです。
ユーザーが入力したQueryStringを実行し結果を表示する関数 Execute-Query を紹介します。
この関数は、SQL*PLUS同様、複数行にわたるQueryStringを実行し、結果を表示することができます。
ただし、SQL*PLUSのようにいきなりSELECT文を書き始めることはできず、List1のように
Execute-Query SELECT文[Enter]
と入力する必要があります。

Execute-Query.ps1

#=========================================================================================
# Execute-Query: QueryStringを実行する
#
# UPDATE 2008/04/28 Ver.1.0.0
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#=========================================================================================
function global:Execute-Query
{
#複数行のQueryStringを受け取る
$strSQL = Read-MultiLine
#QueryStringを実行する
$dtSet = Execute-QueryString $strSQL
if ( $dtSet.Tables.Count -gt 0 )
{
#format-tableコマンドレットでデータを表示
$dtSet.Tables[0].Rows | format-table
}
}
#エイリアス設定
Set-Alias -name EQS -value Execute-Query -scope "Global"
開発ポイントですが、
複数行の入力を受け取ることができるようにSQL*PLUSもどきを作る その5(PowerShell Tips)で紹介した Read-MultiLine関数を使用しています。
入力を受け取った後は SQL*PLUSもどきを作る その3(PowerShell Tips) で紹介したExecute-QueryString関数を実行し、結果を表示しています。
QueryStringを実行するたびに関数名 Execute-Query と入力するのは面倒なので、エイリアス設定をすることをおすすめします。(今回エイリアス名をEQSとしました)
使用方法および実行結果は下記の通りです。

List1

PS > eqs
select * from
emp
;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ----- --- --- -------- --- ---- ------
7369 SMITH CLERK 7902 1980/12/17 ... 800 20
7499 ALLEN SALESMAN 7698 1981/02/20 ... 1600 300 30
7521 WARD SALESMAN 7698 1981/02/22 ... 1250 500 30
7566 JONES MANAGER 7839 1981/04/02 ... 2975 20
7654 MARTIN SALESMAN 7698 1981/09/28 ... 1250 1400 30
7698 BLAKE MANAGER 7839 1981/05/01 ... 2850 30
7782 CLARK MANAGER 7839 1981/06/09 ... 2450 10
7788 SCOTT ANALYST 7566 1987/04/19 ... 3000 20
7839 KING PRESIDENT 1981/11/17 ... 5000 10
7844 TURNER SALESMAN 7698 1981/09/08 ... 1500 0 30
7876 ADAMS CLERK 7788 1987/05/23 ... 1100 20
7900 JAMES CLERK 7698 1981/12/03 ... 950 30
7902 FORD ANALYST 7566 1981/12/03 ... 3000 20

List2

PS > eqs
select
*
from
emp
where JOB='CLERK';
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ----- --- --- -------- --- ---- ------
7369 SMITH CLERK 7902 1980/12/17 ... 800 20
7876 ADAMS CLERK 7788 1987/05/23 ... 1100 20
7900 JAMES CLERK 7698 1981/12/03 ... 950 30
inserted by FC2 system