Base64エンコードされたデータを 実体ファイルに一括復元する「マジック生成」バッチ (PowerShellによる高速処理版)


概要

以前投稿したBase64エンコードでテキスト変換されたデータを 一括で実体ファイルに復元する「かんたん生成」バッチが、
プロンプト画面へのペーストという簡単な操作というのは画期的だなと自負していたのですが、
如何せん、一行ずつプロンプト画面で入力待ちしては変数に代入を繰り返す処理方式だったため、
スループットに難がありました。
ということで、クリップボードから内部的に読み込んで処理できるよう、PowerShellに移植しました。

環境

Windows 10, Windows 7

方法

  1. ファイル作成用シーケンスが存在する記事ページにおいて、
    [Ctrl+A]、[Ctrl+C]キーでテキスト全体をクリップボードにコピーします。
  2. B642FHT.batを起動します。
  3. 同じフォルダ内に、ファイルが生成していることを確認します。

補足事項

  • 本スクリプトは、PowerShellコマンドレットにより、クリップボードからのテキストの読み込み、Base64デコードなどの処理を行っています。

  • ファイル作成用シーケンスは次のような構成にしています。
    ファイル名 <改行> ```又は--- <改行> Base64文字列複数行 <改行> ```又は---

  • 引数にディレクトリパスを指定することで、ファイル・ログ出力先フォルダを指定可能です。

  • 複数ファイルが含まれていても全て生成処理されるようにコーディングしており、
    ブラウザ画面においてファイル作成用シーケンス部分を意図的に選択しなくても、「すべて選択」でページ全体のテキストをコピーすれば良いようになっています。

  • 一つファイルを出力する度に、ログを出力します。スクリプト名が "B642FHT.ps1" のとき、ログファイル名は "B642FHT.log" となります。ログファイルは、処理が成功したかを確認できるようにしているだけですので、削除しても差し支えありません。

ソースファイル

「かんたん生成」するには、B642File.batを起動して本ページ全体のテキストをコピペして下さい。
その後、生成したZIPファイルを解凍して任意の場所へ配置して下さい。

興味ある方は、以下のコードをご覧ください。

コード

B642FHT.bat
@ECHO OFF
PowerShell -ExecutionPolicy RemoteSigned -STA -File %~dpn0.ps1 %1 "nul"
EXIT /B
B642FHT.ps1
$Host.UI.RawUI.ForeGroundColor = "Green"
Add-Type -Assembly System.Windows.Forms
"############# B642FHT.ps1 ##############"
"# Converting data sequence             #"
"#            encoded in Base64         #"
"#       to real files continuously     #"
"# high-throughput script by PowerShell #"
"#                                      #"
"#   1st release: 2019-07-07            #"
"#   Last update: 2019-07-25            #"
"#   Author: Y. Kosaka                  #"
"#   See the web for more information   #"
"#   https://qiita.com/x-ia             #"
"########################################"

$filenameScript = (Get-ChildItem $MyInvocation.MyCommand.Path).BaseName
$dirPathScript = Split-Path $MyInvocation.MyCommand.Path -Parent
$Host.UI.RawUI.WindowTitle = $filenameScript
$extLog = ".log"
$timePause = 1500


function ChDirWork($arg) {
  if (Test-Path $arg.Replace('"', '')) {
    ChDir $arg
    [System.IO.Directory]::SetCurrentDirectory((Get-Location -PSProvider FileSystem).Path)
  }
}

function GetClip {
  $strClip = [Windows.Forms.Clipboard]::GetText()
  return $strClip
}

function ViewClip($strClip) {
  $numSizeClip = $strClip.Length
  $numLineClip = 0
  foreach( $strLine in $strClip -split "`r`n" ){
    ++$numLineClip
  }
  Write-Host "`r`nRead $($numSizeClip.ToString("#,#")) chars ($($numLineClip.ToString("#,#")) lines) from the clipboard.`r`n"
  return $numLineClip
}

function DivText($strClip, $numLineClip, $filenameScript, $extLog) {
  $strOut = $null
  $flagOut = 0
  $numOut = 0
  $numProgressNext = 0
  $numLineProcessed = 0
  foreach( $strLine in $strClip -split "`r`n" ){
    if (($strLine -like "``````*") -Or ($strLine -like "---*")) {
      $flagOut +=1
      if ($flagOut -eq 1) {
        $fileOut = $strLinePrev
      } elseif ($flagOut -eq 2) {
        $err = DecodeB64 $strOut $fileOut
        PutLog $err $fileOut $filenameScript $extLog
        $numOut += 1
        $strOut = $null
        $flagOut = 0
      }
    } elseif ($flagOut -eq 1) {
      $strOut += $strLine
    } else {
    $strLinePrev = $strLine
    }
    $numLineProcessed += 1
    $numProgress = [Math]::Floor(100 * $numLineProcessed / $numLineClip);
    if ($numProgress -ge $numProgressNext) {
      Write-Progress -activity "Processing the text from clipboard" `
      -status "$numProgress % processed" `
      -percentComplete $numProgress `
      -CurrentOperation "$($numLineProcessed.ToString("#,#")) / $($numLineClip.ToString("#,#")) lines, $numOut files created."
      $numProgressNext = $numProgress + 1
    }
  }
}

function DecodeB64($strOut, $fileOut) {
  [System.IO.File]::WriteAllBytes($fileOut, [Convert]::FromBase64String($strOut))
  return $?
}

function PutLog($err, $fileOut, $filenameScript, $extLog) {
  if ("$err" -eq "True") {
    $strResult = "Success"
    Write-Host "Suceeded to create a file $fileOut."
  } else {
    $strResult = "Failure"
    Write-Host "Failed. An error occured."
  }
  $timeStampNow = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss.fff")
  $fileLog = $filenameScript + $extLog
  "$timeStampNow`t$filenameScript`t$strResult`t$fileOut" | `
  Out-File $fileLog -Encoding Default -Append
  $Host.UI.RawUI.WindowTitle = "$filenameScript $strResult"
}

function EoF($timePause) {
  Start-Sleep -milliseconds $timePause
}

ChDirWork $Args[0]
$strClip = GetClip
$numLineClip = ViewClip $strClip
DivText $strClip $numLineClip $filenameScript $extLog
EoF $timePause

バイナリ (Base64 encoding)

B642FHT.zip
---
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
RkhULnBzMVBLBQYAAAAAAgACAHIAAAAlBgAAAAA=
---