2017年9月7日木曜日
2013年12月1日日曜日
PowerShellでシンプルなテンプレートエンジンを作成する
概要
テスト環境や本番環境のアプリリリースにて一部(IPアドレス等)以外、リリース手順が同じ場合
また、メール送信ファイル作成にてユーザ情報以外同一の場合など
毎回、記述するのが面倒なのでシンプルなテンプレートエンジンを作成する
テンプレートファイルと入力データよりファイルを出力する
・テンプレートファイルが存在しない場合はメッセージを出力してなにもしない
・テンプレートの変換は「Hashtable」を使う( @{キー名 = 値; キー名 = 値; ....... })
「Hashtable」の「キー名」にテンプレートに記述した値を設定、「値」に変更する入力データを設定
文字コードのデフォルトは「UTF8」(テンプレートファイル、出力ファイル)
関数
実行例
・テンプレートファイル(Mail_Template.txt)
{LAST_NAME} {FIRST_NAME} 様
ご購入ありがとうございます。
~省略~
・powershell実行
# メールテンプレート指定
$MailTemplateFile = "C:\template\Mail_Template.txt"
# ユーザ情報セット
$User = @{"{LAST_NAME}"="山田"; "{FIRST_NAME}"="太郎"}
# 出力ファイル指定
$MailFile = "C:\Temp\Mail_001.txt"
# 実行
Render-Template -TemplateFilePath $MailTemplateFile -Data $User -OutPutFilePath $MailFile
2013年11月14日木曜日
URLエンコード、URLデコードをする
関数
実行例
# 実行 PS > Get-URLEncode -VALUE "あいうえお" -ENCODING "utf-8" %e3%81%82%e3%81%84%e3%81%86%e3%81%88%e3%81%8a
# 実行 PS > Get-URLDecode-VALUE "%e3%81%82%e3%81%84%e3%81%86%e3%81%88%e3%81%8a" -ENCODING "utf-8" あいうえお
メモ
文字コードの指定「Encoding.GetEncoding」
2013年11月3日日曜日
ファイル名を置換する
関数
実行例
$FolderPath = "C:\sample"
$Include = "*.xls"
$Befor = "\["
$After = "【"
Get-ChildItem $FolderPath -Recurse -Include $Include |
ForEach-Object{
Replace-FileName -FilePath $_.FullName -Befor $Befor -After $After
}
2013年10月24日木曜日
フォルダ配下のファイル名を作成日時順に連番を付ける
関数
メモ
DateTime型をソートする場合、キャスト(変換)しないといけない
Sort-Object {$_.CreationTime -as [DateTime]}
2013年10月14日月曜日
2つのCSVファイルから項目に一致した行を出力
概要
2つのCSVファイル(顧客マスタ、商品マスタ)から、顧客マスタに商品マスタ.商品コードが存在するものをPowerShellを使ってCSV出力する
メモ
CSVファイル
■商品マスタ(items.csv)
ITEM_ID,ITEM_NAME 10000,AAAAAA 10001,BBBBBB 10002,CCCCCC ・・・・ ・・・・■顧客マスタ(customers.csv)
CUSTOMER_ID,ITEM_ID,CUSTOMER_NAME,QUANTITY 8000,10000,aaaaa,100 8000,10002,bbbbb,50 8001,10005,ccccc,1000 ・・・・ ・・・・
SQL文だと以下のような感じ
■SQL
SELECT CUSTOMERS.* FROM CUSTOMERS, ITEMS WHERE CUSTOMERS.ITEM_ID = ITEMS.ITEM_ID
PowerShell その1
$result = Import-Csv c:\items.csv | Select-Object ITEM_ID
Import-Csv c:\customers.csv | Where-Object {$result -match $_.ITEM_ID} | Export-Csv c:\output.csv -NoType
customers.csvが10万件、items.csvが1万件で約数十分ぐらいかかる(※スペックによるがとにかく遅い!!)
PowerShell その2
その1の場合、シンプルだが遅いので
items.csvをHashTableにセット(ITEM_IDに重複がないこと)する方法で解決した(約20秒ぐらいで終わる)
$hash = @{}
Import-Csv c:\items.csv | ForEach-Object {$hash.Add($_.ITEM_ID, $_)}
Import-Csv c:\customers.csv | ForEach-Object {if($hash.Get_Item($_.ITEM_ID)){$_}} | Export-Csv c:\output.csv -NoType
2013年10月6日日曜日
音楽ファイルのタグ情報を取得する
概要
フォルダ配下の音楽ファイルのタグ情報を取得する。
・タグ情報を取得するため「taglib-sharp.dll」を使用する。
以下のサイトより取得後、任意の場所に解凍する。
http://download.banshee.fm/taglib-sharp/2.1.0.0/
ファイル名:taglib-sharp-2.1.0.0-windows.zip
関数
実行例
Get-MusicTagData -MusicFolderPath "C:\develop\flac\MR.BIG\Big, Bigger, Biggest"
メモ
タグ情報/プロパティ情報をすべて取得(※taglib-sharp.dllから取得できるすべて)
$TagLib = "C:\develop\lib\taglib-sharp.dll"
# ライブラリ読み込み
[System.Reflection.Assembly]::LoadFile($TagLib)
# タグ情報を取得するファイル名を指定
$audiofile = [TagLib.File]::Create("C:\develop\flac\MR.BIG\Big, Bigger, Biggest\01 Addicted to that rush.flac")
# タグ情報を取得
$audiofile.Tag
# プロパティ情報を取得
$audiofile.Properties
2013年9月9日月曜日
xmlからログ設定を取得
概要
ログ出力する設定をXMLから取得する関数を作成する。
・初期設定はpsに記述する
・XMLにアペンダを記述して選べるようにする
関数
XML設定
実行例
# XML読込 Set-LogSetting -XMLFilePath "C:\log4ps.xml" -Appender "unit" # ログ出力 Write-DebugLog -VALUE "デバッグ" Write-InfoLog -VALUE "情報" Write-WarnLog -VALUE "警告" Write-ErrorLog -VALUE "エラー"
2013年9月7日土曜日
ファイルサイズでファイルをローテーションする
概要
ログを出し続けるとファイルサイズが大きくなりすぎて、処理が遅くなったり、ログの移動・参照もたいへんなので
ファイルサイズよりローテーションを行う関数を作成
・指定したファイルサイズ以上になったらローテーションを行う
・ローテーションする回数も指定する
・ローテーションしたファイル名は「ログファイル名」+「.」+「回数」
関数
日付でファイルをローテーションする
概要
日付よりローテーションを行う関数を作成
・ファイルの作成日が現在の日付でない場合にローテーションを行う
・ローテーションしたファイル名は「ログファイル名」+「.」+「日付フォーマット」
関数
2013年9月3日火曜日
ファイル名に角括弧[]がついてるとRename-Itemで失敗する
概要
ファイル名に角括弧[]がついてるとRename-Itemで失敗するので、Move-Itemを代用する
関数
# ------------------------------------------------------------------
# ファイル名をリネームする
# 関数名:Rename-File
# 引数 :FilePath 名前を変更するファイルパス
# :NewFileName 新しいファイル名前
# 戻り値:なし
# ------------------------------------------------------------------
function Rename-File([String]$FilePath, [String]$NewFileName){
if(Test-Path -LiteralPath $FilePath -PathType Leaf){
$newFilePath = Join-Path -Path (Split-Path $FilePath -Parent) -ChildPath $NewFileName
Move-Item -LiteralPath $FilePath -Destination $newFilePath
}else{
Write-Host "ファイルが存在しません。ファイル名[ $FilePath ]"
}
}
# ------------------------------------------------------------------
# フォルダ名をリネームする
# 関数名:Rename-Folder
# 引数 :FolderPath 名前を変更するフォルダパス
# :NewFolderName 新しいフォルダ名前
# 戻り値:なし
# ------------------------------------------------------------------
function Rename-Folder([String]$FolderPath, [String]$NewFolderName){
if(Test-Path -LiteralPath $FolderPath -PathType Container){
$newFolderPath = Join-Path -Path (Split-Path $FolderPath -Parent) -ChildPath $NewFolderName
if(Test-Path -LiteralPath $FolderPath -PathType Container){
Write-Host "既に存在するフォルダを作成することはできません。フォルダー名[ $FolderPath ]"
}else{
Move-Item -LiteralPath $FolderPath -Destination $newFolderPath
}
}else{
Write-Host "フォルダが存在しません。フォルダ名[ $FolderPath ]"
}
}
実行例
Rename-File -FilePath "C:\[20130903]新規要件定義\[20130903]Webログイン.xls" -NewFileName "Webログイン.xls" Rename-Folder -FolderPath "C:\[20130903]新規要件定義" -NewFolderName "[20130903]要件定義"
2013年8月29日木曜日
ログレベルによって出力するログを制御する
概要
開発環境・本番環境等でログに出すログレベルが違うので制御できるように関数を作成する
・ログ出力は「Out-LogFile」関数を使用する。なのでログレベルはそれに合わせる。
・引数は出力する文字列のみとする。それ以外の「Out-LogFile」関数に必要な引数を先に指定する。
関数
実行例
### 最初に設定を指定
# ログファイル出力先を指定
[String]$LogFilePath ="C:\common.log"
# ログエンコードを指定
[String]$LogEncoding="UTF8"
# ログレベルを指定する(0:デバック,1:情報,2:警告,3:エラー)
[Int]$LogLevel=1
# 実行例
for ($i = 0; $i -lt 100; $i++) {
Write-DebugLog -VALUE "デバッグ"
Write-InfoLog -VALUE "情報"
Write-WarnLog -VALUE "警告"
Write-ErrorLog -VALUE "エラー"
}
2013年8月27日火曜日
ファイル名、フォルダ名をリネームする
概要
何度もフォルダを右クリックして名前変更していくのが大変なので関数化する
変更するファイル名、フォルダ名とリネームする名前を指定して実行
・指定した「ファイル名」「フォルダ名」が存在しない場合はメッセージ出力してなにもしない
関数
実行例
PS > Rename-File -FilePath "C:\新規テキスト ドキュメント.txt" -NewFileName "test.txt" PS > Rename-Folder -FolderPath "C:\新しいフォルダ" -NewFolderName "sample"
メモ
フォルダ・ファイル存在チェック「Test-Path」
・ファイル存在チェック
PS > Test-Path -LiteralPath <<ファイル名(フルパス)>> -PathType Leaf
・フォルダ存在チェック
PS > Test-Path -LiteralPath <<フォルダ名(フルパス)>> -PathType Container
フォルダ・ファイル名の変更「Rename-Item」
PS > Rename-Item <<ファイル名・フォルダ名(フルパス)>> -newName <<新規ファイル・フォルダ名>>
PowerShellでログ出力
概要
PowerShellでログ出力ができるように関数を作成する
ログ出力するファイルパスと出力内容、ログレベル、文字コードを指定して実行
・ログレベルは「デバック(0)」「情報(1)」「警告(2)」「エラー(3)」のみ
・ログメッセージの形式は「ログ出力時刻 [ログレベル] : ログ内容」
・ログ出力時刻のフォーマットは「yyyy/MM/dd HH:mm:ss.fff」
関数
実行例
for ($i = 0; $i -lt 100; $i++) {
Out-LogFile -LogFilePath "C:\app.log" -Value "デバックログを出力します。" -LogType 0
Out-LogFile -LogFilePath "C:\app.log" -Value "情報ログを出力します。" -LogType 1
Out-LogFile -LogFilePath "C:\app.log" -Value "警告ログを出力します。" -LogType 2
Out-LogFile -LogFilePath "C:\app.log" -Value "エラーログを出力します。" -LogType 3
Out-LogFile -LogFilePath "C:\app.log" -Value "ログの種類を指定しない場合、情報ログを出力します。"
}
「Out-File」と「Set-Content」の違い
別プロセスからの読み込み/書き込み
・「Out-File」の場合、ファイルを読み込むことは可能だが書き込むことはできない
・「Set-Content」の場合、ファイルを読み込むことも書き込むこともできない
2013年8月16日金曜日
Windowsでファイル名に使用できない禁止文字を全角に変換する
概要
mp3ファイルのタグ情報からファイル名にしようとするとき、ファイル名に使用できない禁止文字「\/:*?`"><|」が存在するため
全角「¥/:*?`”><|」に変換して対応する
関数
実行例
# 実行 PS > ConvertTo-UsedFileName -FileName "6/2*(1+2)=?.txt"
2013年8月14日水曜日
Excelをシート単位で検索する
概要
Excelで書かれた設計書から修正対象となる項目をいちいち開いて検索するのはめんどうなので、
指定したExcelファイルからシート単位で検索できるようにする
(行列まで調べるようにしたらやたら遅いのでやめた)
検索対象となるExcelファイルと検索する対象項目を指定して実行
・Excelファイルかどうかの判定は行わない
・検索対象が存在する場合は検索結果に「Excelファイル名(フルパス)」「ワークシート名」を返すようにする
関数
実行例
# 検索対象となるフォルダを指定
$FolderPath = "C:\Project\03.基本設計"
# 検索対象
$Target = "ユーザマスタ"
# 指定したフォルダからExcelファイル「xls」「xlsx 」を取得して検索する
Get-ChildItem $FolderPath -Recurse -Include *.xls,*.xlsx |
ForEach-Object {
# 検索
Select-ExcelByWorkSheet -ExcelFilePath $_.FullName -Target $Target
}
メモ
.Net Frameworkよりインスタンスを生成する
# インスタンス生成 PS > オブジェクト変数 = New-Object クラスの完全修飾名(引数) # メソッドにアクセス PS > オブジェクト変数.メソッド名(引数)
・.NET Framework からCOMオブジェクトを使用する
PS > オブジェクト変数 = New-Object -comobject クラスの完全修飾名(引数)
2013年8月11日日曜日
ExIf情報より画像ファイルを撮影日ごとにフォルダ分けする
概要
デジカメで撮った画像が1つのフォルダの中にたまってしまっているので
ExIf情報より撮影日ごとにフォルダ分けて整理する
・今回はmove(移動)ではなくてcopy(コピー)にする
コピー元(フォルダ)とコピー先(フォルダ)を指定して実行
・指定したコピー元が存在しない場合はコピーを行わない
・指定したコピー先が存在しない場合は作成してコピーを行う
・対象ファイルは「jpeg」「jpg」固定(大文字・小文字は気にしない)
・ExIf情報に撮影日時が存在しない場合は「unknown」フォルダに移動
・コピー先に対象ファイルが存在する場合はメッセージを出力してコピーしない
関数
実行例
# 実行 PS > Copy-ImagesByDateTimeOriginal -CopyFolderPath "C:DCIM" -DestFolderPath "C:DateTimeOriginal"
メモ
.Net Frameworkを呼び出す
[完全修飾名のクラス]::静的メソッド(引数)
画像ファイルのメタデータを取得
PS > [System.Drawing.Imaging.Metafile]::FromFile(<<画像ファイルのフルパス>>)例)
PS >[System.Drawing.Imaging.Metafile]::FromFile("C:\DateTimeOriginal\Blue hills.jpg")
Tag :
PhysicalDimension : {Width=800, Height=600}
Size : {Width=800, Height=600}
Width : 800
Height : 600
HorizontalResolution : 300
VerticalResolution : 300
Flags : 77960
RawFormat : [ImageFormat: b96b3cae-0728-11d3-9d7b-0000f81ef32e]
PixelFormat : Format24bppRgb
Palette : System.Drawing.Imaging.ColorPalette
FrameDimensionsList : {7462dc86-6180-4c7e-8e3f-ee7333a7a483}
PropertyIdList : {282, 283, 296, 20515...}
PropertyItems : {282, 283, 296, 20515...}
フォルダ配下の指定した拡張子のファイル情報を取得(Get-ChildItem)
・引数[-Include]を指定して対象となる拡張子のファイル情報を取得
※複数の拡張子を指定する場合はカンマ「,」を使用
※拡張子の大文字、小文字は気にする必要はなし
PS > Get-ChildItem -Path <<フォルダのフルパス>> -Recurse -Include *.<<拡張子>>, *.<<拡張子>>■補足
例1)フォルダ・ファイル情報を取得
PS > Get-ChildItem -Path C:\sample
ディレクトリ: C:\sample
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2013/07/09 13:59 sample
-a--- 2013/07/09 13:57 0 sample1.txt
-a--- 2013/07/09 13:58 0 sample2.txt
例2)そのまま引数「Include」で拡張子を指定したが取得できない
PS > Get-ChildItem -Path C:\sample -Include *.txt # 表示されない例3)「フォルダのフルパス」の後ろに「\*」を追加して取得可能
PS > Get-ChildItem -Path C:\sample\* -Include *.txt
ディレクトリ: C:\sample
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2013/07/09 13:57 0 sample1.txt
-a--- 2013/07/09 13:58 0 sample2.txt
※サブフォルダ配下取得する場合(Recurseを指定)は特に気にしなくてよかった
パスと子パスを 1 つのパスに結合「Join-Path」
PS > Join-Path -Path <<パス>> -ChildPath <<子パス>>
2013年8月7日水曜日
フォルダ構成のみコピーする
概要
システム開発を行っている中で同一のフォルダ構成を作成する場合がある
・現行プロジェクトのフォルダ構成を新規プロジェクトにも適用
・ソースファイル/設定ファイル等の修正前後の差分をフォルダ構成含めて確認
コピー元(フォルダ)とコピー先(フォルダ)を指定して実行
・指定したコピー元が存在しない場合はコピーを行わない
・指定したコピー先が存在しない場合は作成してコピーを行う
・コピー元のフォルダがコピー先に存在する場合は上書き
・コピー先にコピー元に存在しないフォルダが存在する場合そのまま
関数
実行例
# 実行 PS > Copy-Folder -CopyFolderPath "C:\Project123" -DestFolderPath "C:\Project345"
メモ
新規にフォルダ・ファイルを作成「New-Item」
・引数[-Type directory]を指定して新規にフォルダを作成する
PS > New-Item <<フォルダのフルパス>> -Type directory
・引数[-Type file]を指定して新規にファイルを作成する
PS > New-Item <<ファイルのフルパス>> -Type file
・引数[-Force]を指定して強制上書きする
PS > New-Item <<ファイルのフルパス>> -Type file -Force
フォルダ配下のフォルダ・ファイル情報を取得「Get-ChildItem」
・フォルダ配下のみ取得する
PS > Get-ChildItem -Path <<フォルダのフルパス>>
・引数[-Recurse]を指定してサブフォルダ配下も再帰的に取得する
PS > Get-ChildItem -Path <<フォルダのフルパス>> -Recurse例1) 「C:\sample」フォルダ配下のフォルダ・ファイル情報を取得
PS > Get-ChildItem -Path C:\sample
ディレクトリ: C:\sample
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2013/07/09 13:59 sample
-a--- 2013/07/09 13:57 0 sample1.txt
-a--- 2013/07/09 13:58 0 sample2.txt
例2)「C:\sample」フォルダのサブフォルダ配下も含めてフォルダ・ファイル情報を取得
PS > Get-ChildItem -Path C:\sample -Recurse
ディレクトリ: C:\sample
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2013/07/09 13:59 sample
-a--- 2013/07/09 13:57 0 sample1.txt
-a--- 2013/07/09 13:58 0 sample2.txt
ディレクトリ: C:\sample\sample
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2013/07/09 13:57 0 sample1_2.txt
-a--- 2013/07/09 13:58 0 sample2_2.txt
Get-ChildItemで取得した「Mode(属性)」
| Mode(属性) | 内容 |
|---|---|
| d | フォルダ |
| a | ファイル |
| r | 読み取り専用 |
| h | 隠しファイル |
| s | システムファイル |
文字列すべてを小文字に変換「ToLower()」
・メソッド[ToLower()]を使用して小文字に変換
PS > <<文字列>>.ToLower()例) 英大文字を英小文字に変換
PS > $value = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" PS > $value = $value.ToLower() PS > $value abcdefghijklmnopqrstuvwxyz