PowerShell中如何正确用短横线拼接字符串数组并去除文件名前缀
解决PowerShell分割文件名后拼接出现多余短横线的问题
问题背景
你编写了以下PowerShell代码,意图去除文件名的前缀部分(例如将01 - Chapter 1 - Video 1修改为Chapter 1 - Video 1):
$count = 0 $path = "C:\Videos\" $oldvids = Get-ChildItem -Path $path -Include *.* -Recurse foreach ($oldvid in $oldvids) { $curpath = $oldvid.DirectoryName $name = [System.IO.Path]::GetFileNameWithoutExtension($oldvid) $names = $name.Split(" - ") $names[0] = "" $metadata_title = $names -join "-" $ext = [System.IO.Path]::GetExtension($oldvid) if ($name.StartsWith("new_") -eq $false) { $newvid = $curpath + "/new_" + $name + ".mp4" if ([System.IO.File]::Exists($newvid) -eq $false) { $count++ Write-Output $metadata_title } } }
但运行后发现,类似Chapter 1 - New Video的文件名会被转换为Chapter 1---New Video,出现多余的短横线,需要修正逻辑以保留单个短横线。
问题原因
- 使用
Split(" - ")分割字符串后,将第一个元素设为空字符串,拼接时用单个"-",导致空元素与后续元素之间多出短横线。 - 原文件名中原本的
" - "分隔符被替换成单个"-",多重叠加后就出现了连续短横线。
解决方案
方法一:用-split指定分割次数(最简洁)
直接分割第一次出现的" - ",取分割后的第二部分,完全避免拼接问题:
$count = 0 $path = "C:\Videos\" $oldvids = Get-ChildItem -Path $path -Include *.* -Recurse foreach ($oldvid in $oldvids) { $curpath = $oldvid.DirectoryName $name = [System.IO.Path]::GetFileNameWithoutExtension($oldvid) # 只分割第一次出现的" - ",获取后续部分;无分隔符时保留原文件名 $metadata_title = if ($name -match " - ") { ($name -split " - ", 2)[1] } else { $name } $ext = [System.IO.Path]::GetExtension($oldvid) if (-not $name.StartsWith("new_")) { # 用Join-Path规范拼接路径,避免分隔符问题 $newvid = Join-Path -Path $curpath -ChildPath "new_$name.mp4" if (-not [System.IO.File]::Exists($newvid)) { $count++ Write-Output $metadata_title } } }
方法二:修正Split与拼接逻辑
如果坚持使用Split方法,需移除空元素后,用原分隔符" - "拼接剩余部分:
$count = 0 $path = "C:\Videos\" $oldvids = Get-ChildItem -Path $path -Include *.* -Recurse foreach ($oldvid in $oldvids) { $curpath = $oldvid.DirectoryName $name = [System.IO.Path]::GetFileNameWithoutExtension($oldvid) # 分割时移除空元素,避免首尾空格导致的无效项 $names = $name.Split(" - ", [System.StringSplitOptions]::RemoveEmptyEntries) # 分割后元素数量大于1时,取第二个及以后的元素用原分隔符拼接 $metadata_title = if ($names.Count -gt 1) { $names[1..($names.Count-1)] -join " - " } else { $name } $ext = [System.IO.Path]::GetExtension($oldvid) if (-not $name.StartsWith("new_")) { $newvid = Join-Path -Path $curpath -ChildPath "new_$name.mp4" if (-not [System.IO.File]::Exists($newvid)) { $count++ Write-Output $metadata_title } } }
额外优化建议
- 用
Join-Path代替直接拼接路径字符串,适配不同系统的路径分隔符,代码更健壮。 - 用
-not代替-eq $false,符合PowerShell的习惯写法。 - 增加无分隔符文件名的处理逻辑,避免数组索引越界错误。
内容的提问来源于stack exchange,提问作者Joan Venge
相关产品推荐
相关产品推荐

