我有混合音乐项目,软件会生成每个项目中歌曲的 txt 文件列表。问题是,列表仅使用歌曲的前 36 个字符生成姓名每首歌曲。
我需要更正 txt 文件中的名称,以便它们与原始文件的名称相同,并且我的脚本可以使用列表复制文件。
我创建了一个脚本,分为两个块,其中在第一个块中我读取原始文件并生成一个与 txt 文件内名称同名的变量。
First block (what I managed to do):
读取 Original Musics 文件夹中的原始文件,并创建与 List.txt 文件中同名的变量。
Goal of the first block (what I couldn't do):
当此块中的变量名称与 List.txt 中的名称相同时,脚本会将 List.txt 中的名称更改为变量所关联的原始文件的全名。这样,第二个块就可以使用其中的正确名称读取 List.txt 文件。
注意:
可能出现Original Musics文件夹中有两个同名但不同版本的文件,在这种情况下,这两个文件的完整名称必须在要复制到目标文件夹的List.txt文件中。例如。
List.txt文件中的名称:
Got To Be Real (CM_Gex Bootleg Exten
原名(Original Musics文件夹中的全名):
Cheryl Lynn - Got To Be Real (CM_Gex Bootleg Extended SHORT Re Mix).mp3
Cheryl Lynn - Got To Be Real (CM_Gex Bootleg Extended LONG Re Mix).mp3
变量 $ShortOriginalSongName:
Got To Be Real (CM_Gex Bootleg Exten
Got To Be Real (CM_Gex Bootleg Exten
因为是同一个文件,区别在于一个是长版本,一个是短版本,两个全名都必须在List.txt文件中,也就是说,除了更改list.txt中的名称外,当文件相同时,脚本还必须在List.txt中包含原始的全名
脚本:
$files = "C:\Users\$env:username\Desktop\List.txt"
$location = "G:\Original Musics\"
$destination = "C:\Users\$env:username\Desktop\Copy Selected Musics\"
# First block:
Get-ChildItem -Recurse $location* -Include *.mp3 | % {
$ShortOriginalSongName = $_.Basename.Split("-")[1].Trim();
If ($ShortOriginalSongName.Length -gt 36) {$ShortOriginalSongName = $ShortOriginalSongName.Substring(0, 36)};
};
# Second Block:
Get-Content $files | % {
$result = gci -recurse "$location*$_" -Include *.mp3
If($result) {
Add-Content $destination"AddList.txt" -Value $result.Fullname
$musicName = $result.Name
$tot+=1
Write-Host -ForegroundColor Green "$musicName found on $location!"
Write-Host "$musicName copied to $destination..."
Copy-Item $result.FullName -Destination $destination\$($_.Name)
}
}
Second Block:
读取第一个块中歌曲正确名称生成的 List.txt 文件,并将原始文件复制到复制选定的音乐文件夹中。
答案1
您的代码中有很多对Get-ChildItem
for 的重复调用$Location
,因此我建议创建一个将短名称与其关联文件关联起来的哈希表。
你想要:
整理你的文件:
gci $Location *.mp3 -File -Recurse
创建一个由计算出的短名称和源 FileInfo 对象组成的自定义对象:
[PSCustomObject]@{ 'ShortName' = $_.BaseName.Split('-')[-1].TrimStart().PadRIght(36).Substring(0, 36).TrimEnd() 'FileInfo' = $_ }
按短名称对其进行分组(因为多个文件可以产生相同的短名称)。
因此我们从这个开始:
$files = "C:\Users\$env:username\Desktop\List.txt"
$location = "G:\Original Musics\"
$destination = "C:\Users\$env:username\Desktop\Copy Selected Musics\"
$ShortNameList = gci $Location *.mp3 -File -Recurse | %{
[PSCustomObject]@{
'ShortName' = $_.BaseName.Split('-')[-1].TrimStart().PadRight(36).Substring(0, 36).TrimEnd()
'FileInfo' = $_
}} | Group ShortName
然后将该对象转换为哈希表:
$ShortNameLookup = $ShortNameList | ForEach { $hash = @{} } {
$hash.Add($_.Name , @( $_.Group.FileInfo ))
} { $hash }
然后核心处理使用中的每个条目$files
作为哈希键:
Get-Content $files | %{
If ( $FileInfo = $ShortNameLookup[$_] ) {
Add-Content ( Join-Path $Destination 'AddList.txt' ) $FileInfo.FullName
$FileInfo | %{
Write-Host ( '"{0}" found in "{1}"' -f $_.BaseName , $_.DirectoryName)
}
$FileInfo | Copy-Item -Destination $Destination
}
Else { Write-Host "No files found that match '$_'." }
}
未经测试,但确信逻辑合理。希望上传代码——今晚晚些时候会添加注释。