« ◆青空文庫とPDF化とページレイアウトと「柿の種」 | トップページ | ◇各種フォントでPDF作成 »

■バッチをやめ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でも動くしね。

|

« ◆青空文庫とPDF化とページレイアウトと「柿の種」 | トップページ | ◇各種フォントでPDF作成 »