#はじめに
この記事はFujitsu Advent Calendar 2021 19日目の記事です。
この記事では、元Linux系開発者で、Bashのシェルスクリプトでツール開発をしていた私が、Windowsで同様なことができるPowerShellを勉強して、面白いと感じたことを書きます。
#PowerShellの概要
- マイクロソフトが開発したシェル、スクリプト言語
- 2006年に公開
- 2016年にオープンソース化
- 2018年公開のPowerShell Core 6.0からマルチプラットフォームに対応(Windows、Linux、macOSに対応)
- .NET Framework(Windows PowerShell5系以前)、または、.NET Core(PowerShell Core6系以降)で動作する
- コマンドレット(Linuxのコマンド相当)が使用可能
- パイプライン(Linuxのパイプ相当)やリダイレクトが使用可能
- スクリプトはBashのように、if文やwhile文などの制御構文が使用可能
※詳細はWikipedia参照。
#BashとPowerShellの違い
- Bash
- 扱うのはテキスト
- 変数にはテキストが格納される
- 変数には型がない
- パイプは標準出力で渡されたテキストを標準入力で受け取る
- PowerShell
- 扱うのは.NETランタイムのオブジェクト
- オブジェクトのプロパティやメソッドにアクセス可能
- 変数にはオブジェクトが格納される
- オブジェクトや変数には型がある
- パイプラインはオブジェクトを送る
#オブジェクトの例
PowerShellが扱うのは.NETランタイムのオブジェクトなので、文字列や数値のプロパティやメソッドにアクセスできます。
# 文字列オブジェクトのLengthプロパティで文字数を取得
PS > "abc".Length
3
# ToUpperメソッドで大文字に変換
PS > "abc".ToUpper()
ABC
# 数値リテラルを文字列に変換して文字数を取得、数値リテラルのメソッドにアクセスするには括弧で囲む必要あり
PS > (123).ToString().Length
3
Get-Memberコマンドレットで、オブジェクトや変数の型名や、プロパティ、メソッドを確認できます。
# 文字列オブジェクトの情報取得
PS > Get-Member -InputObject "abc"
TypeName: System.String
Name MemberType Definition
---- ---------- ----------
Clone Method System.Object Clone(), System.Object ICloneable.Clone()
CompareTo Method int CompareTo(System.Object value), int CompareTo(string strB), int IComparab...
Contains Method bool Contains(string value)
CopyTo Method void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int co...
EndsWith Method bool EndsWith(string value), bool EndsWith(string value, System.StringCompari...
Equals Method bool Equals(System.Object obj), bool Equals(string value), bool Equals(string...
GetEnumerator Method System.CharEnumerator GetEnumerator(), System.Collections.IEnumerator IEnumer...
GetHashCode Method int GetHashCode()
GetType Method type GetType()
GetTypeCode Method System.TypeCode GetTypeCode(), System.TypeCode IConvertible.GetTypeCode()
IndexOf Method int IndexOf(char value), int IndexOf(char value, int startIndex), int IndexOf...
IndexOfAny Method int IndexOfAny(char[] anyOf), int IndexOfAny(char[] anyOf, int startIndex), i...
Insert Method string Insert(int startIndex, string value)
IsNormalized Method bool IsNormalized(), bool IsNormalized(System.Text.NormalizationForm normaliz...
LastIndexOf Method int LastIndexOf(char value), int LastIndexOf(char value, int startIndex), int...
LastIndexOfAny Method int LastIndexOfAny(char[] anyOf), int LastIndexOfAny(char[] anyOf, int startI...
Normalize Method string Normalize(), string Normalize(System.Text.NormalizationForm normalizat...
PadLeft Method string PadLeft(int totalWidth), string PadLeft(int totalWidth, char paddingChar)
PadRight Method string PadRight(int totalWidth), string PadRight(int totalWidth, char padding...
Remove Method string Remove(int startIndex, int count), string Remove(int startIndex)
Replace Method string Replace(char oldChar, char newChar), string Replace(string oldValue, s...
Split Method string[] Split(Params char[] separator), string[] Split(char[] separator, int...
StartsWith Method bool StartsWith(string value), bool StartsWith(string value, System.StringCom...
Substring Method string Substring(int startIndex), string Substring(int startIndex, int length)
ToBoolean Method bool IConvertible.ToBoolean(System.IFormatProvider provider)
ToByte Method byte IConvertible.ToByte(System.IFormatProvider provider)
ToChar Method char IConvertible.ToChar(System.IFormatProvider provider)
ToCharArray Method char[] ToCharArray(), char[] ToCharArray(int startIndex, int length)
ToDateTime Method datetime IConvertible.ToDateTime(System.IFormatProvider provider)
ToDecimal Method decimal IConvertible.ToDecimal(System.IFormatProvider provider)
ToDouble Method double IConvertible.ToDouble(System.IFormatProvider provider)
ToInt16 Method int16 IConvertible.ToInt16(System.IFormatProvider provider)
ToInt32 Method int IConvertible.ToInt32(System.IFormatProvider provider)
ToInt64 Method long IConvertible.ToInt64(System.IFormatProvider provider)
ToLower Method string ToLower(), string ToLower(cultureinfo culture)
ToLowerInvariant Method string ToLowerInvariant()
ToSByte Method sbyte IConvertible.ToSByte(System.IFormatProvider provider)
ToSingle Method float IConvertible.ToSingle(System.IFormatProvider provider)
ToString Method string ToString(), string ToString(System.IFormatProvider provider), string I...
ToType Method System.Object IConvertible.ToType(type conversionType, System.IFormatProvider...
ToUInt16 Method uint16 IConvertible.ToUInt16(System.IFormatProvider provider)
ToUInt32 Method uint32 IConvertible.ToUInt32(System.IFormatProvider provider)
ToUInt64 Method uint64 IConvertible.ToUInt64(System.IFormatProvider provider)
ToUpper Method string ToUpper(), string ToUpper(cultureinfo culture)
ToUpperInvariant Method string ToUpperInvariant()
Trim Method string Trim(Params char[] trimChars), string Trim()
TrimEnd Method string TrimEnd(Params char[] trimChars)
TrimStart Method string TrimStart(Params char[] trimChars)
Chars ParameterizedProperty char Chars(int index) {get;}
Length Property int Length {get;}
# 数値オブジェクトの情報取得
PS > Get-Member -InputObject 123
TypeName: System.Int32
Name MemberType Definition
---- ---------- ----------
CompareTo Method int CompareTo(System.Object value), int CompareTo(int value), int IComparable.CompareTo(Syste...
Equals Method bool Equals(System.Object obj), bool Equals(int obj), bool IEquatable[int].Equals(int other)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
GetTypeCode Method System.TypeCode GetTypeCode(), System.TypeCode IConvertible.GetTypeCode()
ToBoolean Method bool IConvertible.ToBoolean(System.IFormatProvider provider)
ToByte Method byte IConvertible.ToByte(System.IFormatProvider provider)
ToChar Method char IConvertible.ToChar(System.IFormatProvider provider)
ToDateTime Method datetime IConvertible.ToDateTime(System.IFormatProvider provider)
ToDecimal Method decimal IConvertible.ToDecimal(System.IFormatProvider provider)
ToDouble Method double IConvertible.ToDouble(System.IFormatProvider provider)
ToInt16 Method int16 IConvertible.ToInt16(System.IFormatProvider provider)
ToInt32 Method int IConvertible.ToInt32(System.IFormatProvider provider)
ToInt64 Method long IConvertible.ToInt64(System.IFormatProvider provider)
ToSByte Method sbyte IConvertible.ToSByte(System.IFormatProvider provider)
ToSingle Method float IConvertible.ToSingle(System.IFormatProvider provider)
ToString Method string ToString(), string ToString(string format), string ToString(System.IFormatProvider pro...
ToType Method System.Object IConvertible.ToType(type conversionType, System.IFormatProvider provider)
ToUInt16 Method uint16 IConvertible.ToUInt16(System.IFormatProvider provider)
ToUInt32 Method uint32 IConvertible.ToUInt32(System.IFormatProvider provider)
ToUInt64 Method uint64 IConvertible.ToUInt64(System.IFormatProvider provider)
# 変数を定義して、変数の型情報を調べてみる
PS > $a = 1.23
PS > Get-Member -InputObject $a
TypeName: System.Double
Name MemberType Definition
---- ---------- ----------
CompareTo Method int CompareTo(System.Object value), int CompareTo(double value), int IComparable.CompareTo(Sy...
Equals Method bool Equals(System.Object obj), bool Equals(double obj), bool IEquatable[double].Equals(doubl...
GetHashCode Method int GetHashCode()
GetType Method type GetType()
GetTypeCode Method System.TypeCode GetTypeCode(), System.TypeCode IConvertible.GetTypeCode()
ToBoolean Method bool IConvertible.ToBoolean(System.IFormatProvider provider)
ToByte Method byte IConvertible.ToByte(System.IFormatProvider provider)
ToChar Method char IConvertible.ToChar(System.IFormatProvider provider)
ToDateTime Method datetime IConvertible.ToDateTime(System.IFormatProvider provider)
ToDecimal Method decimal IConvertible.ToDecimal(System.IFormatProvider provider)
ToDouble Method double IConvertible.ToDouble(System.IFormatProvider provider)
ToInt16 Method int16 IConvertible.ToInt16(System.IFormatProvider provider)
ToInt32 Method int IConvertible.ToInt32(System.IFormatProvider provider)
ToInt64 Method long IConvertible.ToInt64(System.IFormatProvider provider)
ToSByte Method sbyte IConvertible.ToSByte(System.IFormatProvider provider)
ToSingle Method float IConvertible.ToSingle(System.IFormatProvider provider)
ToString Method string ToString(), string ToString(string format), string ToString(System.IFormatProvider pro...
ToType Method System.Object IConvertible.ToType(type conversionType, System.IFormatProvider provider)
ToUInt16 Method uint16 IConvertible.ToUInt16(System.IFormatProvider provider)
ToUInt32 Method uint32 IConvertible.ToUInt32(System.IFormatProvider provider)
ToUInt64 Method uint64 IConvertible.ToUInt64(System.IFormatProvider provider)
ハッシュテーブルなどのデータ構造もオブジェクトとして使用できます。
# ハッシュテーブルを初期化、変数に格納
PS > $hash_table = @{
>> 'key1' = 'value1'
>> 'key2' = 'value2'
>> 'key3' = 'value3'
>> }
# キーから値を取得
PS > $hash_table['key1']
value1
# Keysプロパティでキーの一覧を取得
PS > $hash_table.Keys
key3
key1
key2
# Valuesプロパティで値の一覧を取得
PS > $hash_table.Values
value3
value1
value2
#パイプラインの動作
PowerShellのパイプラインはオブジェクトを送るため、Linuxのパイプと比べると複雑なルールでコマンドレット間が接続されます。
ルールを一言で言うと、「送り元のコマンドレットの出力オブジェクトの型に応じた、送り先のコマンドレットのパラメーターが自動的に適用される」となります。
#「コマンドレットのパラメーター」は、Linuxで言うところの「コマンドのオプション」に相当。
以下では、JSONを変換するConvertFrom-Jsonコマンドレットでのパイプラインの動作を見てみます。
# ConvertFrom-Jsonのhelpを確認、JSON文字列を渡せばよさそう
PS > help ConvertFrom-Json
名前
ConvertFrom-Json
概要
Converts a JSON-formatted string to a custom object.
構文
ConvertFrom-Json [-InputObject] <System.String> [<CommonParameters>]
~省略~
# JSON文字列を渡してみる、別のオブジェクトに変換されて出力される
PS > $json = '{
>> "name" : "taro",
>> "age" : 18,
>> "job" : "engineer"
>> }'
PS > $json | ConvertFrom-Json
name age job
---- --- ---
taro 18 engineer
# 試しにHashtableオブジェクトを渡してみる
PS > $hash_table = @{
>> 'name' = 'taro'
>> 'age' = 18
>> 'job' = 'engineer'
>> }
PS > $hash_table | ConvertFrom-Json
ConvertFrom-Json : 無効な JSON プリミティブです: System.Collections.Hashtable。
発生場所 行:1 文字:15
+ $hash_table | ConvertFrom-Json
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [ConvertFrom-Json], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.ConvertFromJsonCommand
※パイプラインは実際にはもっと複雑なルールで動作します。詳細は参考文献を参照。
#PowerShellで作成したツールの紹介
テスト用の環境構築で、「ユーザーとグループを作成し、ユーザーをグループに追加」を手作業で行っていたのを、以下のようなスクリプトで自動化しました。
# 作成するユーザーの配列
$users = @('Test_User1', 'Test_User2', 'Test_User3', 'Test_User4', 'Test_User5')
# パスワードはSecureString型に変換する必要がある
$password = convertto-securestring 'Test_Password' -AsPlainText -Force
foreach($user in $users) {
# ユーザー作成
New-LocalUser -Name $user -Password $password
}
#作成するグループの配列
$groups = @('Test_Group1', 'Test_Group2')
foreach($group in $groups) {
# グループ作成
New-LocalGroup -Name $group
}
# ユーザー、グループの紐づけ情報(ハッシュテーブル)
$user_group = @{
'Test_Group1' = @('Test_User1', 'Test_User2')
'Test_Group2' = @('Test_User3', 'Test_User4', 'Test_User5')
}
foreach($entry in $user_group.GetEnumerator()) {
foreach($value in $entry.Value) {
# ユーザーをグループに追加
Add-LocalGroupMember -Group $entry.Key -Member $value
}
}