PowerShell 文件和子文件夹中的文件重命名

3

我对PowerShell还比较陌生,已经阅读了很多示例,并使用“Get-ChildItem”示例炸糊了我的大脑。

我有一个影片文件夹结构如下:

Films
├─Film1
| Film1Name.mp4
│ └─Subs
│   └─English.SRT
│
├─Film2
| Film2Name.mp4
│ └─Subs
│   └─English.SRT
|
├─Film3
| Film3Name.mp4
│ └─Subs
│   └─English.SRT

我想要实现的目标是将*.srt文件重命名并上移一个文件夹级别,然后将其重命名为电影的文件名或电影文件夹的名称,并在扩展名前插入.ENG。 接着,递归删除未使用的“Subs”文件夹。
最终结果应该如下所示,基于文件名:
├─Film1
| Film1Name.mp4
│ Film1Name.ENG.SRT

根据文件夹名称进行此操作。
├─Film1
| Film1.mp4
│ Film1.ENG.SRT

任何帮助都将不胜感激,两种方法都可以使用

我在尝试别人发布的代码时,误删了我的测试文件夹

$rootPath = "c:\Test"

Get-ChildItem -Path $rootPath -Directory | ForEach-Object {
 
    $targetFolder = $_.FullName
    Resolve-Path "$targetFolder\*" | ForEach-Object {
        Move-Item -Path "$_\*.SRT" -Destination $targetFolder -Force
        Remove-Item -Path $_
    }
}

谢谢,我会尝试一下。 - Welshcheese
使用这个工具后,我的文件夹里只剩下一个名为“.ENG.SRT”的文件,其他所有文件和文件夹都被删除了。 - Welshcheese
2个回答

2

首先,在设置根目录后,您需要获取所有以“films”命名的顶级目录列表。

Set-Location -Path "Your directory path here"
$Films = Get-ChildItem -Directory

完成此操作后,我们可以遍历每一个文件夹,将该文件夹的路径推入其中,并检查是否存在名为“Subs”的文件夹。Pop-Location在完成我们需要做的操作后会将我们带回之前的位置。

foreach ($Film in $Films) {
    Push-Location $Film
    if ((Get-ChildItem -Directory).Name -contains "Subs") {
        # Do stuff
    }
    Pop-Location
}

如果我们找到一个名为"Subs"的文件夹,我们需要检查是否存在".SRT"文件。我们可能拥有多种语言的字幕。
$Subs = Get-ChildItem -Path *.srt -Recurse

检查$Subs是否为非空。

if ($null -ne $Subs) { }

将任何“.SRT”文件移动到当前位置并按指定的名称进行重命名。
foreach ($Sub in $Subs) {
    $FilmPath = $Film.Fullname
    $FilmName = $Film.Name
    $SubtitleLang = $Sub.BaseName.Substring(0,3).ToUpper()
    $Extension = $Sub.Extension
    Move-Item -Path $Sub -Destination "$FilmPath\$FilmName.$SubtitleLang$Extension"
}

如果您确定要删除“Subs”文件夹,我们将首先检查它是否为空。如果仍有文件剩余,我们可以编写一条消息。
$RemainingFiles = Get-ChildItem -Path Subs -Recurse
if ($null -eq $RemainingFiles) {
    Remove-Item -Path Subs -Force
}
else {
    Write-Warning "There are still files in $($Film.FullName)\Subs"
}

将所有内容整合在一起
Set-Location -Path "Your directory path here"
$Films = Get-ChildItem -Directory

# Loop through the Films
foreach ($Film in $Films) {
    Push-Location $Film
    if ((Get-ChildItem -Directory).Name -contains "Subs") {
        # Find any SRT files in the "Subs" directory
        $Subs = Get-ChildItem -Path Subs/*.srt -Recurse
        if ($null -ne $Subs) {
            foreach ($Sub in $Subs) {
                $FilmPath = $Film.Fullname
                $FilmName = $Film.Name
                $SubtitleLang = $Sub.BaseName.Substring(0,3).ToUpper()
                $Extension = $Sub.Extension
                Move-Item -Path $Sub -Destination "$FilmPath\$FilmName.$SubtitleLang$Extension"
            }
        }
    }

    # Remove the Subs folder
    $RemainingFiles = Get-ChildItem -Path Subs -Recurse
    if ($null -eq $RemainingFiles) {
        Remove-Item -Path Subs -Force
    }
    else {
        Write-Warning "There are still files in $($Film.FullName)\Subs"
    }

    # Return to the root directory for the next folder.
    Pop-Location
}

首先感谢您的回复,非常详细、清晰和易懂。 它开始帮助我更好地理解。它不是将.SRT文件重命名为"Film1.ENG.SRT",而是将其重命名为没有扩展名的"Film1"。同时,是否有可能将电影文件名与文件夹名称同时重命名,并保留原始扩展名? - Welshcheese
已更新以根据语言前三个字母重命名字幕。对于英语,这将是您问题中指定的 ENG。如果电影文件名与文件夹名称不同,则我无法更改电影文件名。 - Ash
你可以给它起任何名字,你可能有不同的媒体类型,可能会有多个媒体文件等。 - Ash
是的,它在所有测试文件夹上都失败了。 一些字幕文件的名称为03English.srt,1English,10_ENGLISH等,大多数以数字开头,取决于DVD / Bluray上的顺序。 我应该将其作为保存的.ps1运行还是通过我正在使用的ISE运行? - Welshcheese
1
谢谢,它有效了,正如我所说,我可以用BRU重命名电影名称。非常感谢,这节省了我很多手动操作的时间。 - Welshcheese
显示剩余3条评论

0

据我理解,如果您知道有多少个文件夹(电影)的话,这个方法可能会起作用:

1..3|ForEach {Copy-Item -Path C:\Films\Film$_\Subs\English.srt -Destination C:\Films\Film$_\Film$_.ENG.SRT} 
1..3|ForEach {Remove-Item -Path C:\Films\Film$_\Subs -Recurse -Force}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接