param( $Path, $Index = "H:\AnimeLib", [switch] $Single, [switch] $Force, [switch] $Sub ) Import-Module -Name ($PSScriptRoot + "\PathChar.psd1") Import-Module -Name ($PSScriptRoot + "\NameRegex.psd1") Edit-PathChar $Path #$TargetName = "俺だけ入れる隠しダンジョン〜こっそり鍛えて世界最強〜"; $TargetName = "" #$DestinName = "真の仲間" Write-Output $Path #$Index = "L:\AnimeLib" #$Path = "L:\Anime\202001 ネコぱら\[Nekomoe kissaten][Nekopara][01-12][BDRip][1080p][CHT]\[Nekomoe kissaten][Nekopara][12][1080p][CHT].mp4" #$Path = "L:\Anime\202004 ストライク・ザ・ブラッド OVA IV\[Suzu-Kaze][Strike_the_Blood_IV_OVA][01-12FIN][BDRip_1080P][HEVC_YUV420P10]\[Suzu-Kaze] Strike the Blood IV 12FIN [BDRip 1920x1080 HEVC YUV420P10 FLAC].mkv" #$Path = "H:\Anime\201901 盾の勇者の成り上がり\[LKSUB][Tate no Yuusha no Nariagari][01-25][GB][720P][MP4]\[LKSUB][Tate no Yuusha no Nariagari][01][GB][720P].mp4" #$Path = "H:\Data\Downloads\因為不是真正的夥伴而被逐出勇者隊伍\[Shin no Nakama][01][BIG5][1080P].mp4" $JsonPath = $("$Index\Anime\* $TargetName", $($Path -replace '(.*\\[^\[\\\]]*)\\\[.*', '$1') | ? {Test-Path $_}) $WorkData = $(if (Test-Path "$JsonPath\animelibk.json") { Get-Content "$JsonPath\animelibk.json" | ConvertFrom-Json } else { "" | select ID, WorkName, TargetName, DestinName, Season, Episode }) # 確認資料狀態,缺少則進行物件資料建立 if (-not($WorkData.WorkName)) { $WorkData.WorkName = Read-Host "請輸入作品名稱:"; } if (-not($WorkData.TargetName)) { $WorkData.TargetName = $($JsonPath -replace '.*\\[0-9\s]*(.*)$', '$1'); } if (-not($WorkData.DestinName)) { $WorkData.DestinName = Read-Host "請輸入目的地名稱:"; } if (-not($WorkData.Season)) { [int] $WorkData.Season = Read-Host "請輸入季別:"; } if (-not($WorkData.Episode)) { $WorkData.Episode = @(); } $WorkData #$Seasons_TC = "", "第一季", "第二季", "第三季", "第四季", "第五季" $Seasons_TC = "", "Seasons 1", "Seasons 2", "Seasons 3", "Seasons 4", "Seasons 5" $Lang = @{ Season = "Season {0:00}" } $Year = @($($JsonPath -replace '.*\\((?\d{4})?(?\d{2})?).*$', '${Y}'), $(get-date -Format 'yyyy')) | ? {-not([string]::IsNullOrEmpty($_))} | Select -First 1 # 取得目標資料夾是否存在,不存在建立資料夾,並取得資料夾物件 $LinkPath = "{2}\{0}\{1}" -f $WorkData.DestinName, $($Lang["Season"] -f $WorkData.Season), $Index $LinkDir = $(if (-not(Test-Path -Path "$LinkPath*")) { New-Item -Path "$LinkPath ($Year)" -ItemType Directory -Force } else { Get-Item -Path "$LinkPath*" }) #$DestDir = $(New-Item -Path ".\$WorkData.DestinName\$($Seasons_TC[$WorkData.Season]) ($Year)" -ItemType Directory -Force) function Get-StandName { param ( $FileObj ) # 進行傳入變數判斷,非 FileInfo 物件則視為 String,先進特殊字元處理,再取得物件 $File = $(if ($FileObj.GetType().Name -eq 'FileInfo') { $FileObj } else { Get-Item -Path $(Edit-PathChar $FileObj) }) # 因應檔名不同而設定多組正規方式 $EpisodeRegex = @( "(?:S\d{2})?[\s]?-[\s]E?(?\d{2})" "[\[\b\s](?\d{2})[\s_]?(?:[vV]\d|END|FIN)[\]\b\s]" "\[(?\d{1,2})\D{2}\]" "\[(?\d{1,2})\]" ) $NameRegex = @( "[\[\b\s](?[^\[\]]*)[\]\b\s]?$" ) $Result = $File.Name | % { Get-NameRegex $_ -Regex $EpisodeRegex } | % { $(Get-NameRegex $_["L"] -Regex $NameRegex -Exclude "(BD|DVD|HDTV)RIP|BIG5" -End) + $_ } | Select -First 1 # 建立回傳資料物件,以方便後續資料處理。 $OutputData = "" | Select newName, Season, Episode, newFullName; $OutputData.newName = $Result.Name; $OutputData.Season = $WorkData.Season; $OutputData.Episode = [int] $Result.Episode; $OutputData.newFullName = "{0} S{3:00}E{1}{4}{2}" -f $Result.Name, $Result.Episode, $File.Extension, $WorkData.Season, $(if($Sub) {".default"}); return $OutputData; } ### Select Object Mode START ### # 建立自定屬性 File 和運算公式 $FileObj = @{ label = "File"; Expression = {$_}; } # 建立自定屬性 NewName 和運算公式 $NewNameObj = @{ label = "NewName"; Expression = {Get-StandName $_}; } $StructPathObj = @{ label = "StructPath"; #Expression = {$(New-Item -Path $(".\{0}\{1} ({2})" -f $WorkData.DestinName, $Seasons_TC[$WorkData.Season], $Year) -ItemType Directory -Force).FullName}; Expression = {$LinkDir}; } ### # Select Object Mode END ### # 運作模式 if ($Single) { # 單集模式 $List = @(Get-Item -Path $(Edit-PathChar $Path)) $BuildList = $List | select $FileObj, $StructPathObj, $NewNameObj | ? {$_.NewName.Episode -notin $WorkData.Episode} #$BuildList | ? {$_.NewName.Episode -notin $WorkData.Episode} | Format-List } elseif ($Sub) { $List = @(Get-Item -Path $(Edit-PathChar $Path)) $BuildList = $List | select $FileObj, $StructPathObj, $NewNameObj | ? {$_.File.Extension -in @(".ass", ".ssa")} } $ENDResult = $BuildList | % { $Command = @{ ItemType = 'HardLink' Path = $("{0}\{1}" -f $_.StructPath, $_.NewName.newFullName) Target = $(Edit-PathChar $_.File.Fullname) } #try { if (New-Item @Command) { Write-Host $_.NewName.newFullName $_.NewName } #} catch { #} } #$ENDResult #$ENDResult.gettype(); if (-not($Sub)) { $ENDResult | % { if ($_.Episode) { $WorkData.Episode += $_.Episode }}} $WorkData | ConvertTo-Json | Out-File -Encoding "UTF8" "$JsonPath\animelibk.json" exit 0; ##### 以下試寫或測試用 ##### # SIG # Begin signature block # MIIFxwYJKoZIhvcNAQcCoIIFuDCCBbQCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQU5uOMlGEFPkqdlQakIgaEB5Z+ # +o2gggNSMIIDTjCCAjagAwIBAgIQV5lzhhF94bJEhqpMRjsGlzANBgkqhkiG9w0B # AQUFADAqMRMwEQYDVQQDDApOaWNrIENoYW5nMRMwEQYDVQQKDAplYXJpY2sub3Jn # MB4XDTIyMTAzMTE3NTEzNVoXDTIzMTAzMTE4MTEzNVowMzEiMCAGCSqGSIb3DQEJ # ARYTcGNuaWNrMTAwQGdtYWlsLmNvbTENMAsGA1UEAwwETmljazCCASIwDQYJKoZI # hvcNAQEBBQADggEPADCCAQoCggEBANj4xp1L4NLChJS8NthMMln7V6LccMjvtf6P # UNBk4TaV6bGCLAtwT1AcU2X+uloOag85JqhEu6zR4yFZqNDcKq5eXVZsd3HIH4nH # q1H5GAF3LNPhGj7DXjBdwrZTpMcmYJ81CaWbDJzjTAEd3MkCGNilpvRMVSNC7l/L # TSojIp4N1tvIqsT2tqU8i9vSKeXZhgWVSx27HbIP54J+VpcLqB9YUPUdeLxpYdIQ # GlCk3s/5zzpZUBLsns/OJgJmoXcModBxOIfPlchDODqTn6TVzKdszLdXfjymtx1t # eF812HHGkZnzov3uKQV3n6zuM/lfcRxVbCuIT5UzBZX7BF/DTAkCAwEAAaNnMGUw # DgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMB8GA1UdIwQYMBaA # FBXyUrhn78ppKe7GRmHS6vbsNae/MB0GA1UdDgQWBBSJSdIOoqzCt5WY6WJNZ4MO # CQGPaDANBgkqhkiG9w0BAQUFAAOCAQEAUkJt4vMLRqdtBu+gWw/EGGvRLQYriQhv # d1FHCK8gC1O3s5tre9y3fuLpx06fCvERRf544Q02EaKq6MtgODZVroe1EUJ5YxZR # K0iDpW/uolGXMth1U+Pb2Y9XrFa8LuYJcq+B5QE1eb5BSLDmgN5ML02eHoh523xs # pq7moIexPszsneLhtW+qAUrgi4zi4JCLmssLIC7OdfnA+sFcj+y9f0OtBZPeq5Oi # XTIrnft6uVOoeSy4UCZ3arbIG/28+CJ+U8lMro+Gput/OaV5ctZmh3K/bjoXJ1oW # TeAge6EFyw4ARhr1QyxpFFLNtuKGC3Y437L0tUzx5tGRQdyhHtm8RTGCAd8wggHb # AgEBMD4wKjETMBEGA1UEAwwKTmljayBDaGFuZzETMBEGA1UECgwKZWFyaWNrLm9y # ZwIQV5lzhhF94bJEhqpMRjsGlzAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEK # MAigAoAAoQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3 # AgELMQ4wDAYKKwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQU/vzDaztSiU0uZW5A # zigjELjN82swDQYJKoZIhvcNAQEBBQAEggEAZN4tpg3ppYZ1zQ/ZGyb2Qr9wD+7j # HN4A3p+S/2BMIfKniEu06vR3F4ot14Zbg5iP1OXTlb8fqBKs2M0xxyLfR7Bw8EhR # NkKnDq3NuUFLZCsq/+zhpWRcUQSmXViM0YcvpGi6kzU9Ho1oUdo/+Yn/zXNwnMRf # dejcnbmNynAazqdxmpoI1VKbRqSEWcH97xZ8il7GVQuj4SeH3ojwD8onApz8SNyB # ebKUfEPaMhEWFuHbHNYibuKn4KfjmU9o/Duh9Gy4Qyd7RVqU9lSBJrugjwIq++nU # DiBJKIFMlGrTp8ZCy/kdCAozUMIUsARv+gXQrE6lP6fSKjD4xP9WJBLt6Q== # SIG # End signature block