PowerShell Cookbookが良すぎる
先日『PowerShellポケットリファレンス』をとりあえずは読了して、『PowerShell Cookbook』(3rd edition)を読み始めたが、
改めて実用的なサンプルが盛りだくさんだと感動している次第。1000ページもあるのにどのレシピも役に立つものばかりだ。
例えば、$PSDefaultParameterValuesの具体的な使い方。ハッシュでまとめて指定したり、スクリプトブロックで動的に指定したり、共通パラメータCredentialの既定値をワイルドカードで一括指定したり。
情報がAbout Topicsと少数のWebページくらいしかないようなことでも、とてもコンパクトに要点を押さえて書かれているので貴重な書籍だと思う。
ダウンロードできるサンプルコードも豊富で良質だ。当分はCookbook先生から学んでいこうと思う。
3rd editionはPowerShell 3.0までしかカバーしていないので、来年あたりに4th出ないかなと気になっている。それにしても3rdは初版の2倍近くのページ数。
次は何ページになるんだろう。紙の本だと本棚のスペースをとるのでKindle版一択だなあ。Kindle版だと半額近いし。洋書はKindle化されてるものが多くてしかも安くていいな。
4.0の情報を補完する意味でも、Cookbookと並行してAbout Topicsも少しずつ読んでいきたい。
配列のflatten
配列において
((1,2), (3,4))→(1, 2, 3, 4)
とflattenするメソッドを追加してみた。
<?xml version="1.0" encoding="utf-8" ?> <Types> <Type> <Name>System.Array</Name> <Members> <ScriptMethod> <Name>Flatten</Name> <Script> function _flatten { $args[0] | % { if($_ -is 'Array') { _flatten $_ } else { $_ } } } _flatten $this </Script> </ScriptMethod> </Members> </Type> </Types>
型データディレクトリ$typedirを適当に作成し、上の内容をSystem.Array.ps1xmlで保存し、プロファイルで
Update-Typedata -PrependPath $typedir\System.Array.ps1xml
とすれば使える。
サンプル
> ((1,2),(3,4))[1] 3 4 > ((1,2),(3,4)).Flatten()[1] 2
vimからpowershell
set shell=C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe
としておくと色々うれしい。
:r !Get-Date
で日時挿入。
:r !ls $doc -directory -recurse *hoge* | % fullname
でリンク集完成。
(パス名上でgfでそのファイルを開く。フルパスでなくてもvimのpath変数から名前解決してくれる。空白文字を含む時はVで行選択してgfでOK。)
:sh
でPowerShell起動。
:!{command}
でPowerShellのコマンド実行。
1点残念なのは、PowerShellコマンドに入力を渡す時だ。
:w !{command}
とすると
発生場所 行:1 文字:5 + {command} <C:/Users/foo/AppData/Local/Temp/VIi890A.tmp + ~ 演算子 '<' は、今後の使用のために予約されています。 + CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordEx ception + FullyQualifiedErrorId : RedirectionNotSupported
matchit.vimの設定
ftplugin\ps1.vimに以下を記述
let b:match_words = "if:else,(:),{:},[:],<#:#>,@\":\"@"
これで % により
<# と #>, if と else, @" と "@
間で移動できるようになってスッキリ。
CubePDF用の一括リネームスクリプト
CubePDFではjpgで保存すると既定ではdocument-001.jpg, document-002.jpg, ...という連番ファイル名になる。
これを変更するにはファイル名入力フォームをマウスでクリックしてファイル名を入力すれば良いのだが、
キーボードだけで済ませたいのでスクリプトを書いてみた。ついでに日時も入れられるようにした。
ps1ファイル
<# .SYNOPSIS 番号違いのファイルを一括リネーム .DESCRIPTION ファイル名末尾に通し番号のついたファイル hoge001.foo のフルパスを引数に与えると、 同じディレクトリの番号違いのファイル hoge002.foo, hoge003.foo, ...も一括して fuga001.foo, fuga002.foo, ... にリネームする。(fugaはユーザー入力) 通し番号のついていないファイル hoge.foo が与えられると、 単にfuga.fooにリネームされる。 また、ファイル名先頭に日時を入れるか選択できる。 #> param([string]$file) $useTimestamp = (Read-Host "ファイル名に日時を入れますか?(y/n)") if($useTimestamp -eq 'y') { $ts = Get-Date -f "yyyyMMdd hh-mm-dd" } else { $ts = '' } $title = (Read-Host "タイトルを入力してください") $parent = Split-Path $file -parent $leaf = Split-Path $file -leaf $basename = $leaf -replace '(\d+)?(\..+)$', '' # hoge001.foo -> hoge gci "$parent" "$($basename)*$($matches[2])" -file | % { # hoge*.fooなファイル $_.FullName -match '(\d+)?\..+$' | Out-Null $parts = ( $ts, $title, $matches[0] ) | ?{ $_ -ne '' } $leaf = $parts -join ' ' $fullname = Join-Path $parent $leaf ren $_.FullName $fullname }
batファイル
powershell.exe "C:\script\rename.ps1" %1
使い方
CubdPDFの外部プログラムにbatファイルを指定して、
> ps | Out-Printer CubePDF
を実行すると、プロセス一覧がCubePDFによってPDF, JPEG等に保存される。
ファイル名にはタイムスタンプ(任意)、指定したタイトルが入る。
GMail認証に失敗するとき
Send-MailMessageでハマったのでメモ。
GMailに5.5.1 Authentication Required.と言われる時は、新しい端末またはアプリからのログインなのでGMail独自の2段階認証が必要な可能性がある。
しかし2段階認証に非対応なアプリ(Send-MailMessageするスクリプトもこれにあたる?)もある。そんなアプリのためにGMailはアプリ固有パスワードを用意している。
https://support.google.com/accounts/answer/185833?hl=ja
ここで生成された固有パスワードを通常のパスワードの代わりに用いれば無事認証される。
使用したコード
$cred = Get-Credential $from Send-MailMessage -To $to -From $from -Subject $subject -Body $body ` -SmtpServer $smtp -Credential $cred -UseSsl -Port 587 -Encoding UTF8