■バッチをやめPowerShellスクリプトを書いてみる
Windowsバッチは大変すぎ
Windowsバッチでは変数の取り扱いや、コマンド呼び出しの引数設定、さらには文字コード設定がほぼ破綻した状態になっています。
そこでスクリプトはPowerShellに移行することにしました。
入口は.batとし、拡張子が.ps1となっているPowerShellスクリプトを呼ぶ
例えばconvertコマンドを実装するにはconvert.batとconvert.ps1を用意し、動作はconvert.ps1に書き、.batファイルは次の固定コードを書きます。
---- convert.bat @echo off set "POWER_SHELL_FILE_PATH=%~dp0%~n0.ps1" powershell -ExecutionPolicy RemoteSigned -File %POWER_SHELL_FILE_PATH% exit
convert.ps1にはPowerShellのスクリプトを置きます。
---- convert.ps1 try{ # なんだかんだ } catch{ $_.Exception.Message | Out-File -FilePath err.log -Append echo 異常発生 $_.Exception.Message } pause
実例
実例を載せます。
次の場所からダウンロードできます。
http://k-hiura.cocolog-nifty.com/blog/files/pdf_cvt_set.zip
pdf_cvt_set +-- A01_convert.bat 処理入口 +-- A01_convert.ps1 処理実態 +-- A00_clean.bat PDFの削除 +-- texts | +-- *.txt 青空文庫からダウンロードしたtxt | `-- *.jpg 青空文庫からダウンロードした画像 +-- PDFs | `-- (*.pdf) 作成されたPDFファイル +-- (book_set.txt) .txtと.pdfの対応記述 +-- bin +-- AozoraPDF.py `-- 青空文庫.jpg
これは前の記事◆青空文庫をPDF化するツール (ソースも公開) AozoraPDFを使いtextsフォルダに置かれた複数の青空文庫txtファイルから複数のPDF文書をPDFsフォルダに生成するスクリプトになっています。
convert.batをクリックするとtxtファイル内に書かれた情報を元に.pdfファイル名を作成します
.txtと.pdfの対応はbook_set.txtに書かれ、同じ変換を行わないように制御されています。
try{
$THIS_DIR ="$PSScriptRoot"
$BOOK_SET_FILE="$THIS_DIR\book_set.txt"
$BIN_DIR ="$THIS_DIR\bin"
$TEXTs_DIR ="$THIS_DIR\texts"
$PDFs_DIR ="$THIS_DIR\PDFs"
# 配列の宣言
$book_set_array=@()
# 配列の宣言
$array = @()
# 指定ファイルがあるか調べる
if (Test-Path $BOOK_SET_FILE) {
# ファイルを1行ずつ読む
Get-Content -Path $BOOK_SET_FILE | ForEach-Object {
# 結果(1行)を変数にセットする
$line = $_
# Write-Outputの代わりにechoでよい。echoを書かず変数だけでも表示される
echo $line
# ";"で分断する
$firstPart, $secondPart = $line -split ";"
# ファイルパスを指定
$file1Path = "$TEXTs_DIR\$firstPart"
# 配列に記憶
$file2Path = "$PDFs_DIR\$secondPart"
# 注意ForEach-Objectはcontinueでは繰り返しにならない
if(-not (Test-Path $file1Path)) { return }
$file1 = Get-Item -Path $file1Path
if(-not (Test-Path $file2Path)) { return }
$file2 = Get-Item -Path $file2Path
# 更新時刻の比較
if ($file1.LastWriteTime -gt $file2.LastWriteTime) {
echo "$file1Path は $file2Path より新しい"
python $BIN_DIR\AozoraPDF.py -in $file1Path -out_dir $PDFs_DIR
}
# 配列に記憶
$array += $file1Path
$book_set_array += $line
}
}
$changed="n"
# 指定拡張子
$extension = "*.txt"
# 指定ディレクトリ内の指定拡張子を持つファイル一覧を取得
$files = Get-ChildItem -Path $TEXTS_DIR -Filter $extension
foreach ($file in $files) {
$full_path=$file.FullName
# 配列の中に文字列が含まれるか(含まれないか)チェックする
if ($array -notcontains $full_path) {
echo "$full_path は array に含まれません"
$command="python $BIN_DIR\AozoraPDF.py -in $full_path -out_dir $PDFs_DIR"
# コマンドを実行して結果を取得する
$result=Invoke-Expression $command
$book_set_array += $result
$changed="y"
}
}
echo "--- NEW BOOK SET ---"
$book_set_array
echo "--------------------"
# 変数のチェック
if( $changed -eq "y" ){
$userInput = Read-Host "book_set.txtを上記内容で置き換えますか? (y/n)"
if ( $userInput -eq "y" ){
Set-Content -Path $BOOK_SET_FILE -Value $book_set_array -Encoding UTF8
echo $BOOK_SET_FILEを置き換えました
}
}
else{
echo "変更はありません"
}
}
catch{
$_.Exception.Message | Out-File -FilePath err.log -Append
echo 異常発生 $_.Exception.Message
}
pause
echo文はかなり特殊で思った通りの出力を得ることができないことが良くあります。
次の例もかなり苦労したecho文です。
# for ループを使用して配列を回す for ($i = 0; $i -lt $arrayLength; $i++) { echo ("array[$i]=" + $array[$i]) }
う~ん。癖が強すぎ
誰も使わない理由は分かった。
bashも相当おバカだけど、これほど変ではない。
結局直接実行せず呼び出しになるなら、Pythonあたり書いた方が良い気がしてきた。WindowsでもLinuxでも動くしね。
| 固定リンク