どうも、PowerShellと出会ってからというもの、オブジェクト指向型でないコマンドラインシェルが時代遅れに見えて仕方ない天井冴太です。
Zshだと、ターミナルを開き直しても以前やったコマンドの履歴が参照出来て地味に便利。確かBashもそうだった気がする。PowerShellでは出来ないのか?とググって、以下の記事に辿り着いた。
PowerShell - このコマンドレット、この前実行した、ような・・・・・・ - Qiita
ふむふむ成る程。prompt
関数内でGet-History
した結果をExport-Csv
して、それをImport-Csv
するコードを自分のプロファイルのファイルに書き込めば可能と。
で、上記記事中のコードには、記事自体でも明記されているが、幾つかの問題点が残されている。
上2つは解決出来そうだ。3つ目もある程度は緩和出来そう。という訳でチャレンジ……出来た!
$historyFilePath = "~/.posh_history.csv"
Import-Csv $historyFilePath | Add-History
function prompt {
$latestHistory = Get-History -Count 1
if($script:lastHistory -ne $latestHistory) {
$csv = ConvertTo-Csv $latestHistory
if( -not(Test-Path $historyFilePath)) {
Out-File $historyFilePath -InputObject $csv[0] -Encoding UTF8
Out-File $historyFilePath -InputObject $csv[1] -Encoding UTF8 -Append
}
Out-File $historyFilePath -InputObject $csv[-1] -Encoding UTF8 -Append
$script:lastHistory = $latestHistory
}
return "$pwd >"
}
- 入力無しEnterで重複する履歴が保存されるのは、その時には履歴情報の更新が行われないから。毎回、直前の履歴を$script:lastHistoryに格納しておき、それと現在の最新の履歴を比較する事で、履歴の更新の有無を判断している。
- 元のコードでは、追記するレコードをマニュアルで構築してる。故にエスケープ処理の抜けが発生しているのだが、CVSへの変換だけであれば
ConvertTo-Csv
が使える。ConvertTo-Csv
の結果の最終行を取り出せば、それが求めるレコードの内容となる。
- 同様に、元のコードではマニュアルで構築しているCSVファイルのヘッダ(シリアライズした型の名前、各フィールドに対応するメンバの名前)2行も、
ConvertTo-Csv
の結果の先頭2行が使える。
後は、現状prompt
関数に直書きしているのを別の関数に独立させれば、なおシンプルになるだろう。
しかし、そもそも履歴のファイルへの保存が追記でないといけないのかは疑問。PowerShellで記憶出来る履歴の最大件数は$MaximumHistoryCountに設定された値(デフォルトは64)で、それを超えると古いものから捨てられる。ファイルに保存されている履歴の件数が$MaximumHistoryCount以下であれば問題ないが、それを超えると、古い情報は無意味になり、しかもファイルは際限なく太っていく。情報を追加するだけのAdd-History
ではなく、実行も行うInvoke-History
を使うというならば話は別だが、毎回上書きした方が良いのではないかと思う。エクスポートの為のコードも、「Get-History | Export-Csv -Path $historyFilePath
」だけで済むしね。
- オブジェクト指向型でないコマンドラインシェルが時代遅れに見えて仕方ない
えーマジテキスト出力型コマンドラインシェルー? テキスト出力型コマンドラインシェルが許されるのは2009年までだよねー!
- Bashもそうだった気がする
- Bash使ってたの昔過ぎて憶えてない。
Export-Csv
- 勿論
Export-Clixml
でも良い筈である。以降のCVS読み書き周りについても同じ事が言えるが、特に断りは入れない。
exit
以外の方法でPowerShellを終了させると、直前の履歴が保存されない。
- これは、どういう意味かよく分かってない。
ConvertTo-Csv
-
CSVに限った話ではないが、ConvertTo-Csv
が在るのに何故Export-Csv
なんて物があるんだろう。要はExport-Csv
の内容をファイルにリダイレクトすればいい訳で、専用のコマンドレットが必要とは思えない。
(そういう意味では、Out-File
の存在も謎だ。)