Create a gist now

Instantly share code, notes, and snippets.

@GNQG /bmsext.ps1
Last active Oct 14, 2016

Extract BMS archives with appropriate directory structure
function Get-CommonDirectoryPath($paths){
# original: https://www.rosettacode.org/wiki/Find_common_directory_path#PowerShell
switch($paths.Count){
0{return $null}
1{
$s=$paths[0].TrimStart('/').Split('/')
$v=''
for($r = 0; $r -lt $s.Count-1; $r++) {
$v+=$s[$r]
}
return $v
}
}
$p=New-Object System.Collections.ArrayList
for($i=0; $i -lt $paths.Count; $i++) {
$dummy=$p.Add(($paths[$i].TrimStart('/').Split('/')))
}
$c = -1
$found = $false
do {
$t = $p[0][++$c]
for($r = 1; $r -lt $p.Count; $r++) {
if ($t -ne $p[$r][$c]) {$found=$true; break }
}
} until ($found)
$s=''
for($i=0; $i -lt $c; $i++) {$s += "/"+$p[0][$i]}
return $s.TrimStart("/")
}
function Extract-BmsArchives(){
$archives=@(Get-ChildItem -Name *.zip,*.rar,*.7z)
$reg="(?im:^\d{4}-\d{2}-\d{2}\s*\d\d:\d\d:\d\d\s*([A-Z.]{5})\s*\d+\s*\d+\s*(.+)\s*$)"
$reg_bms="(?i:^.*\.[bp]m([sel]|son)$)"
$reg_exc_dir="(^|/?)(_MACOSX/)"
$reg_exc_file="(^|/?)(Thumbs\.db|desktop\.ini|\.DS_Store)$"
$reg_relpath="^/?(([^/]+/)*)[^/]+$"
foreach($arc in $archives){
$dirs=New-Object System.Collections.ArrayList
$files=New-Object System.Collections.ArrayList
$bmsfiles=New-Object System.Collections.ArrayList
[Regex]::Matches(
[string]::Join("`n",@(7z l $arc)),$reg
) | foreach{
$property=$_.Groups[1].Value
$path=$_.Groups[2].Value.Replace('\','/')
if ($property.StartsWith('D')){
if ($path -notmatch $reg_exc_dir){
$dummy=$dirs.Add($path)
}
}else{
if ($path -notmatch $reg_exc_file){
$dummy=$files.Add($path)
}
if ($path -match $reg_bms){
$dummy=$bmsfiles.Add($path)
}
}
}
$com_pre=Get-CommonDirectoryPath($files)
$com_pre_bms=Get-CommonDirectoryPath($bmsfiles)
if($com_pre -ne $com_pre_bms){
"***Skipped: $arc***"
}else{
$dirdict=@{}
foreach($entry in $files){
$extpath=[Regex]::Match($entry.Substring($com_pre.Length),$reg_relpath).Groups[1].Value
if (-not $dirdict.ContainsKey($extpath)){
$dirdict[$extpath]=New-Object System.Collections.ArrayList
}
$dummy=$dirdict[$extpath].Add($entry)
}
$dirname=$null
if ($args -contains "-DirNameMajored"){
$dirname=[System.IO.Path]::GetFileNameWithoutExtension($com_pre)
}
if (-not $dirname){
$dirname=[System.IO.Path]::GetFileNameWithoutExtension($arc).TrimEnd(". ")
}
foreach($childdir in $dirdict.Keys){
[String]::Join("`n",$dirdict["$childdir"].ToArray()) | Set-Content -path tmpfilelist.dat -encoding UTF8
"7z e -aos -o""$dirname/$childdir"" ""$arc"" `@tmpfilelist.dat"
$dummy=(7z e -aos -o"$dirname/$childdir" "$arc" `@tmpfilelist.dat)
if ($LASTEXITCOD -gt 0){
"7z failed with error code $LASTEXITCODE"
exit 1
}
}
}
}
}
Extract-BmsArchives
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment