はじめに
この記事を書くにあたって、下記2点が満たせるようにを意識しました
- 実務で使える実例集になってること
- 何度も読み返せる辞書的になってること
- 基本コマンドの解説も兼ねてて初心者や非IT向けになってること
PowerShellは、プログラムを学んでみたいと考えてる非ITの方にうってつけだと思います。
何故なら、簡単、すぐ結果が出る、面倒で繰り返し系の作業に特に力を発揮だからです。
One-Linerで片付けろ
免責
PowerShellのバージョンによって動かなかったり誤字で動かなかったりするかもしれませんがご了承下さい。
また、章番号や順番は都度大きく変わる可能性があります。
後、順次、コマンドは追加していきます。
1-1. Build系
1-1-1. スクリプトの実行ポリシーを確認
Get-ExecutionPolicy
これがRestrictedになってると実行出来ない
1-1-2. 管理者としてPowershellを実行してからスクリプトの実行ポリシーを最低限安全なのに変更
Set-ExecutionPolicy RemoteSigned
Powershellアイコンを右クリックで管理者として実行じゃ
1-1-3. Profileの場所確認
Test-Path $profile
1-1-4. Profileを作成
Profileを作っておけば、powershellを立ち上げて一番最初に読みこむスクリプトを書いておけるのじゃ
1-1-5. 定数を定義する
Set-Variable -name HOME_DIR -value "C:\Users\makoto\" -option constant
1-1-6. 長いコマンドが面倒なので省略形で入力する為のコマンドを確認する
Alias
1-1-7. 速くて全部確認出来なかったのでAliasをゆっくり確認する
alias|more
わかったから抜けるって場合はqじゃ
1-1-8. Aliasを定義する
Set-Alias less Invoke-Item
Set-Alias excel "C:\Program Files (x86)\Microsoft Office\root\Office16\excel.exe"
プログラムもオッケー!
1-1-9. 自動変数を確認する
Get-Variable
Profileの位置や定数定義した値が表示されるのじゃ
1-1-10. Path環境変数を見やすく確認
(ls env:path).value -split ";"
1-1-11. Pathに追加する
$env:path += "C:\Users\makoto\Program\"
1-1-12. すべての環境変数を取得する
Get-ChildItem env:
1-1-13. 使えるアセンブリ確認
[Appdomain]::CurrentDomain.GetAssemblies()|%{$_.GetName().Name}
1-1-14. 使いたいアセンブリ追加
add-type -AssemblyName System.Windows.Forms add-type -AssemblyName Microsoft.VisualBasic
1-1-15. ドライバと主な情報を見やすく取得
Get-WmiObject -query "Select * from Win32_PnPSignedDriver"|ft DeviceName,DriverProviderName,DriverVersion
1-2. ディレクトリ移動系
1-2-1. 今いる場所を確認
pwd
1-2-2. 今いる場所のディレクトリ一覧を確認
ls -dir
1-2-3. 1つ下のディレクトリに移動
cd ディレクトリ名
1-2-4. 1つ上のディレクトリに移動
cd ../
1-2-5. 今のディレクトリを覚えておく
Push-Location
1-2-6. どこか移動した後さっきのディレクトリに戻る
Pop-Location
1-3. 対話系
1-3-1. 普通に文字列をコンソールに出す
"普通の文字列"
1-3-2. コンソールに入力した文字を変数に格納する
$InputData = Read-Host "何の値を入れますか?"
1-3-3. やりたいことを選ばせる
"仕事頑張る","休憩する","もう帰りたい"|ogv -PassThru -Title 次に何をしますか?
1-3-4. 少し落ち着く
start-sleep -Milliseconds 400
1-3-5. Powershellの実行結果を実行元に返す
$Process = start powershell -PassThru -ArgumentList "-WindowStyle Maximized -noexit -command get-date"
1-3-6. 何分まで系のタイマー
do{$start=get-date;$end="20:30";$diff=New-TimeSpan $start $end;sleep 1}while($diff.Minutes -gt 0)
1-3-7. 別窓立ち上げて終わるまで待つ
Wait-Process (start powershell -PassThru).Id
1-3-8. lsの実行結果を選択したものをオブジェクトとして返す
$Selected = ls |Out-GridView -PassThru
1-4. 条件分岐系
1-4-1. ifで条件分岐
if(1 -eq 1) {"いちです"}else{"lとかの間違いだと思います・・・"}
1-4-2. Switchで条件分岐
switch(1..5|ogv -PassThru){"1"{"いちです"}"2"{"にです"}default{"3-5です"}}
1-5. 監視系
1-5-1. リアルタイムに書き込まれるログを監視
cat ./20170615_log.txt -wait -tail 10
いわゆるtail -fですな
1-5-2. ちょっと待つ
sleep 2
1-5-3. 時間比較
if(((New-TimeSpan (Get-Date) "15:00").Ticks -ge 0)) {"未来の時間"}
1-5-4. ポップアップ立ち上げて通知してくれる
[System.Windows.Forms.MessageBox]::Show("おーい","タイトル","YesNo","Information")
1-5-5. 時間になるまで1分毎に監視する
do{$start=get-date;$end="2017/6/15 15:00";$diff=new-TimeSpan $start $end;sleep 1;}while($diff.Ticks -gt 0)
1-5-6. 実行ログを別窓で立ち上げてファイルを常時監視
$TailLogProcess = start powershell -PassThru -windowstyle normal -argumentList "-command cat $LOGFILE -wait -tail 10"
1-6. 関数系
1-6-1. どこからでも呼びだせるグローバル関数を定義する
function global:TestFunc{"test"}
1-6-2. 関数のパラメータを設定する
function global:TestFunc{param($引数 = "初期値")$引数}
TestFuncと実行すると"初期値"が。TestFunc 1と実行すると1が返る。
1-6-3. 関数のパラメータの中の初期値でファイルのリストを読み込む
param($RemoteFileList = ${Import-Csv "RemoteFileList.csv" -Encoding Default))
1-6-4. 関数のパラメータで選択したものを設定する
param($project=$(ls -name -dir $BUSINESS_DIR|ogv -PassThru -Title "どのプロジェクトを選択?"
1-6-5. 関数のパラメータで-autoオプションが指定されたらAutoModeになるような分岐をする
param([Switch]$Auto) if($Auto){"AutoMode"}
1-6-6. 関数のパラメータを複数設定する
param($WorkDir,$RemoteFileList,$Auto)
1-6-7. 関数の中で作業ディレクトリに移動してから元の場所に返ってくる
begin{Push-Location .;cd $WorkDir)process{ls}end{Pop-Location}
1-6-8. ハッシュで曜日タイプを定義してしかも選ばせる
$曜日 = @{0="平日";1="土曜";2="日曜"}|ogv -PassThru
1-6-9. 引数からファイルを指定させる(レガシーな書き方)
if($args[0]){$File=$args[0]}else{$File=Read-Host "Fileを指定して下さい。"}
1-6-10. パラメータをパイプから渡せるようにする
param([Parameter(ValueFromPipeline)]$WorkDir)
version2以下だとValueFromPipeline=$trueって書かないとダメらしいのう
1-6-11. パラメータをパイプから渡さるようにしてしかも必須にもする
param([Parameter(ValueFromPipeline,mandatory)]$WorkDir)
2-1. ファイル情報取得系(ls系)
2-1-1. 今いる場所のディレクトリ/ファイル一覧を取得
ls
2-1-2. 今いる場所以下のps1ファイルを取得する
ls -r *.ps1
2-1-3. 名前が最新のcsvを1つlsする
ls *.csv|sort -descending|select -first 1
2-1-4. 自分の今いるディレクトリ名を取得する
Split-Path -Leaf (Split-Path -Parent (ls).fullname)|get-Unique
2-1-5. 拡張子抜きの名前を取得する
(ls Test.txt).basename
2-2. ディレクトリ・ファイル操作系
2-2-1. ファイルを作成する
ni test.txt -type file
2-2-2. ファイルをコピーする
cp test.txt text2.txt
2-2-3. ディレクトリを作成する
mkdir Newdir
3-1. エクセル操作系
3-1-1. エクセルファイルを静かに開く
$excel=New-Object -comobject Excel.Application;$excel.DisplayAlerts = $false;$excel.Visible = $false;
3-1-2. エクセルファイルを開いてBook取得
$book = $excel.Workbooks.Open("$XLSFILE")
3-1-3. シート選択
$sheet = $book.Workheets.Item($SheetName)
3-1-4. エクセルの行、列に何かデータを埋め込む
$sheet.Cells.Item(9,1) = "9行目のA列"
3-1-5. 用意しておいたCSVデータからエクセルの行、列に何かデータを埋め込む
$WriteDataList|%{$sheet.Cells.Item([int]$_.行,[int]$_.列) = ($_.WriteData)}
エクセルに上書き出来るので重宝じゃ
3-1-6. ヘッダから数えて余計な行を削除
$sheet.Rows.item(1).Delete()
3-1-7. ヘッダから数えて余計な列を削除
$sheet.Colums.item(1).Delete()
3-1-8. エクセルデータを同じ形式で新規保存
book.SaveAs("report.xlsx")
3-1-9. 1つのエクセルファイルにある複数のシートをCSVで一括保存
$book.sheets|%{($book.WorkSheets.Item($_.name)).Activate();$book.SaveAs((Convert-Path .)+"\"+$_.name+".csv",6)}
3-1-10. Excelを閉じる
$excel.Quit();$excel = $null
3-2-1. ファイルを開く
$CSVData = Import-Csv "CSVFileList.csv" -Encoding Default
3-2-2. 行をあいまい抽出
$CSVData|?{$_.列名 -like "流*誠*")
3-2-3. 行をAかBどちらかで抽出
$CSVData|?{$_.列名 -like "流石[誠][真]"
3-2-4. 行をequal条件で抽出
$CSVData|?{$_.isOpen -eq "TRUE"}
3-2-5. 列選択
$CSVData|select 列A,列B,列C,列D
3-2-6. 列Dを元に降順で並び替える
$CSVData = $CSVData|sort 列D -Descending
3-2-7. 列を追加する
$CSVData|Add-Member -MemberType NoteProperty -Name "追加列" -Value "追加しました"
いわゆるCustomObjectのpropety追加じゃ
3-2-8. 行と列を組み合わせた条件でデータ抽出
$CSVData|?{$_.出身星 -eq "アセチルコリン"}|%{$_.Name = "流石誠"}
3-2-9. 重複項目を取得する
$double = $CSVData|?{if(($Code -eq $_).count -ge 2){$_}}|unique
3-2-10. CSVDataをMergeする
$CSVData = $CSVData_1 + $CSVData_2 + $CSVData_3 + $CSVData_4
3-2-11. lsの結果とCSVの特定列の結果を重複項目抜きで取得する
$list=(compare (ls -name -dir) $csvData.ProjectID|?{$_.SideIndicator -eq "<="}).InputObject
3-2-12. グループ別にまとめて名前と件数カウント
$CSVData|group なんとかホールディング|%{$_.Name + " :" + $_.count;}
3-4. TEXTデータ操作系
3-4-1. 10行目から読み込み
Get-Content OutputList.csv|select -skip 9
3-4-2. textを1行ずつ読み込んでって行数つけてあげる
$i=0;Get-Content .test.txt|%{"$i"+":"+$_";$i++}
3-5. 文字列操作系
3-5-1. コロンのマークで区切ってコロン単位で区切った配列に格納
$コロン単位で区切った配列 = $コロン付き文字列 -split ":"
3-5-2. 現在の生年月日を文字列表現
(Get-Date).ToString("yyyy");(Get-Date).ToString("MM");(Get-Date).ToString("dd")
3-6. 集計系
3-6-1. CSVデータ列の値のアベレージ、最大、最小、数量、合計を求める
Import-Csv "集計データ.csv" -Encoding Default|measure "列名" -ave -max -min -sum
3-6-2. CSVデータの集計したい列の合計値を変数に格納する
$合計値 = (Import-Csv "集計データ.csv" -Encoding Default|measure "列名" -sum).sum
3-7. 計算系
3-7-1. 普通に計算する
1+1
3-7-2. 2乗する
[Math]::Pow(2,4)
3-7-3. CSVに計算式を書いておいて計算実行
ipcsv .\CalcList.csv -Encoding Default|%{invoke-expression $_.Formura}
3-8. 検証系
3-8-1. 型を調べる
$var.GetType().FullName
3-8-2. CSVデータの特定列を再帰的に5桁越えチェックする
Import-Csv "CheckDataList.csv" -Encoding Default|%{if($_.列.Length -gt 5) {$_.列 + "が5桁越えてる"}}
3-8-3. 重複チェック
$CheckDataList|?{if(($CheckDataList -eq $_).count -ge 2{$_}} > list.txt
3-9. コマンド実行系
3-9-1. グローバル関数が置いてあるディレクトリのps1群を全部使えるようにする
(ls $関数置き場/*.ps1|select fullname).fullname|%{. $_}
profileに書いておくといいのう
3-9-2. &を使ってCSVデータに書いてある文字列を再帰的にコマンド実行
Import-Csv "ExeList.csv" -Encoding Default|%{&_.FuncCode $_.引数列1 $_.引数列2}
3-9-3. 階層を2階層下まで辿って実行したいps1ファイルを実行する
ls -dir -name|ogv -PassThru|%{cd $_;ls -dir -name|ogv -PassThru|%{cd $_;(ls *.ps1).FullName|ogv -PassThru|%{&$_}}}
3-10. プロセス系
3-10-1. エクスプローラ立ち上げ
start .
3-10-2. 電卓アプリ立ち上げ
$calc = start calc -PassThru
3-10-3. プロセス取得
Get-Process -name powershell
3-10-4. プロセスが終了するまで待機
Wait-Process -Id ($ProcessName.Id)
3-10-5. プロセス停止
Stop-Process -Id ($ProcessName.Id)
3-10-6. プロセスをKill
$calc.Kill()
3-10-7. Powershellを別プロセスで起動してそのまま今の窓で実行
`start powershell -PassThru -NoNewWindow
exitで返ってくるぞ
3-10-8. Powershellを別プロセス別窓で起動
start powershell -ArgumentList "-noexit -command get-date"
3-10-9. Powershellを別プロセス別窓しかも大画面で起動して実行プロセスを元窓に戻す
$ps = start powershell -PassThru -ArgumentList "-WindowsStyle Maximized -noexit -command get-date"
4-1. 出力系
4-1-1. 上書きしてファイル出力
"上書き" > output.txt
4-1-2. 追記してファイル出力
"追記" >> output.txt
4-1-3. CSVDataを出力
$CSVData|Export-Csv export.csv -encoding defalut -NoTypeInformation
-NoTypeInformation抜きだと先頭行にメッセージが出てうざいのじゃ
4-1-4. XLSDataを出力
$book.SaveAs("絶対パス\report.xlsx")
4-1-5. XLSDataをCSVに変換して出力
$book.SaveAs((Split-Path(Convert-Path $XLSFile) -parent) + "\" + $CSVFile,6)
4-1-6. 時刻と自身のファイルの開始終了ログ出力
(date).ToString() + " :" (Split-Path -Leaf $PSCommandPath) + "Ready." >> $LOGFILE
(date).ToString() + " :" (Split-Path -Leaf $PSCommandPath) + "Finished." >> $LOGFILE
4-2. キーボード入力系
4-2-1. キーボードから入力する感じで9*9を入力する
[System.Windows.Forms.SendKeys]::SendWait("9{*}9=")
4-2-2. キーボードから入力する感じでコピー(Ctrl+C)する
[System.Windows.Forms.SendKeys]::SendWait("^(C)")
4-2-3. キーボードから入力する感じでペースト(Ctrl+V)する
[System.Windows.Forms.SendKeys]::SendWait("^(V)")
4-2-4. 電卓開いて9*9を計算する
$calc=start calc -PassThru;sleep 1;[Microsoft.VisualBasic.Interaction]::AppActivate($calc.id);[System.Windows.Forms.SendKeys]::SendWait("9{*}9=")
これ、電卓アプリはあくまでサンプル。色々応用しまくれるぞ!
4-3. レポート系
4-3-1. エクセルレポート作成
$book=$excel.Workbooks.Open((Convert-path $XLSFile)); $sheet=$book.Worksheets.Item($SheetName);$WriteDataList|%{$sheet.Cells.Item($_行,$_.列)=($_.WriteData)};$book.SaveAs((Split-Path(Convert-Path $XLSFile) -parent) + "\" + "report.xlsx")
超無理やり1行につなげました感・・・シェル芸人になるにはまだまだだ・・・
5-1. 終了系
5-1-1. 窓を閉じる
exit
5-1-2. 終わりに
Qiitaの皆さんの記事、本当に毎日参考にさせてもらっておるのでこれからもよろしくじゃ