zip
7zip
poweshell
Extract

Powershellと7zipで拡張子を明示しタイムスタンプを継承してパスワード付き圧縮/解凍をする

今更7-zipのコマンドラインのVBScript

これと同じことをPowershellでもできないか悩んでいたのですが

Powershellでファイルの拡張子をドット抜きで取得する方法 get extensionname without dot /Period

これができたので、VBSと比較的近い形でPowershellで圧縮することができるようになりました。


VBSにはない付加機能 zipファイルのタイムスタンプ承継

このスクリプトは1つのファイルを圧縮することを前提にしています。

このため圧縮するファイルのタイムスタンプを取得して、できあがったzipファイルのタイムスタンプが同一になるようにしています。

このためいちいちファイルを開かなければいつのファイルかわからない、ということがなくなります。


Compress.ps1

#Ver 20190109

$strFileName ="C:\hoge\hoge.txt" # 圧縮する対象のzipファイル
$strPassWord ='Password' #呪文
$7zip="C:\Program Files\7-Zip\7z.exe" #7zipのある場所
if((Test-Path $strFileName) -eq $true){
$ofile = Get-childItem -Path $strFileName #ファイルの存在をテスト
if($ofile.PSIsContainer-eq $false){ #ファイルかフォルダか確認
if([string]::IsNullOrEmpty($ofile.extension)){Write-Host "no extention";$strExtension='' #拡張子がなければNullStringを返す
}Else{
$strExtension = ( $ofile.extension.Substring(1,$ofile.extension.Length-1)) ;
Write-Host $strExtension
}
$strBasename= $ofile.BaseName
$strParent= $ofile.DirectoryName
$strNewFileName =(Join-Path $strParent $strBasename)
$strNewFileName += "_"
$strNewFileName += $strextension
$strNewFileName += ".zip"
#Get File timestamp
$DTCr = $ofile.CreationTime
$DTMd = $ofile.LastWriteTime
$DTAc = $ofile.LastAccessTime
Write-Host $strNewFileName
#すでにzipファイルがあるときはskipする
if((Test-Path $strNewFileName) -eq $False){
# 7-Zipのコマンドライン引数を生成
$Arg=" a -y -p" + $strPassWord + " "+ $strNewFileName +" "+ $ofile.FullName

# 7-zipで圧縮
Start-Process -Wait $7zip -Verb runas -ArgumentList $Arg -WindowStyle Minimized
$ofile = (get-childitem $strNewFileName)
# Set zip file timestamp
$(get-childitem $ofile.FullName).CreationTime=$DTCr
$(get-childitem $ofile.FullName).LastWriteTime=$DTMd
$(get-childitem $ofile.FullName).LastAccessTime=$DTAc
}
} #if($ofile.PSIsContainer-eq $false)
} #if((Test-Path $strFileName) -eq $true)



参考先との埋めがたい実力差

PowerShellと7zipでファイルを圧縮

ここを参考にしているのだが、うまく動かない。


動かない点その1 圧縮オプション

これの

-mem=AES256 

というのはなぜか有効ではなかった。64bitだからだろうか?


動かない点その2 7z.exeの場所の取得


$path=Split-Path ( & { $myInvocation.ScriptName } ) -parent

これもダメだった。このため上記コードでは直接実行ファイルのフルパスを書いている。


動かない点その3 管理者モード

Start-Process $7zip -Verb runas -ArgumentList $Arg

これは絶対わからない... -Verb runas が管理者として実行になります。しかしこれはなくても動きます。


解凍


ps_Extractwith7zip.ps1

#Ver 20190109

$strFileName ="C:\hoge\hoge_txt.zip" # 解凍する対象のzipファイル
$strPass = "Password" #呪文
$7zip ="C:\Program Files\7-Zip\7z.exe" #7z.exeのフルパスを記載してください
if((Test-Path $strFileName) -eq $true){
$ofile = Get-childItem -Path $strFileName #ファイルの存在をテスト
#$strParent = $ofile.PSParentPath.Replace("Microsoft.PowerShell.Core\FileSystem::","")
$strParent=$ofile.DirectoryName
$commandstring = " x -y -p" + $strPass + " " + $strFileName + " -o" +"""" + $strParent +"""" + " -aoa" #問答無用で同名のファイルを上書きする。
Start-Process $7zip -Wait -Verb runas -ArgumentList $commandstring -WindowStyle Minimized
}


-aoスイッチ

-ao (Overwrite mode) switch

-aos Overwrite All existing files without prompt.問答無用で上書き -yスィッチもいれると問答無用度が増す

-aos Skip extracting of existing files. 上とは逆で同名のファイルがあればスキップ。

-aou aUto rename extracting file (for example, name.txt will be renamed to name_1.txt).

同名のファイルがあれば既存のファイルに枝番を付す

-aot auto rename existing file (for example, name.txt will be renamed to name_1.txt).

同名のファイルがあればいまから解凍しようとするファイルに枝番を付す。

普通の枝番をつける方法はこれ。 -aouはちょっと珍しいし、既存のファイルの方をいじるのは感心しない。


-oについて

この後ろが出力先フォルダですが、どこにも書いていないけど、スペースが入っているフォルダの場合はダブルクォーテーションで囲んだ方がよいようです。


参考

17.ファイルの存在するディレクトリパスを取得する


VBS版

こちらに記載しています。

https://qiita.com/Q11Q/items/0d0d41fb858407a74212