删除文件与文本列表进行比较时的匹配问题
Remove matching issues when files are compared to a text list
我有一些这样的文件
Hooligans (BDrip (1080).mkv
Hocus Pocus [DIVX - ITA] - Walt Disney - HQ-.avi
Ho Cercato Il Tuo Nome h265.avi
Ho Cercato Il Tuo Nome 720.rar
Halloween 2 - Il Signore Della Morte.avi
Highlander 2 1080p.mkv
Heartbreakers - Vizio di famiglia.avi
Il cavaliere oscuro.mkv
Il cavaliere oscuro - il ritorno 1080p.mkv
在同一目录中,我有一个文本文件 (movielist.txt
),它的格式总是这样:name + year.
年份始终来自 19**-20**
并且在方括号
内
Hooligans (1995)
Hocus Pocus (1993)
Ho cercato il tuo nome (2012)
Halloween 2 – Il signore della morte (1981)
Highlander 2 – Il ritorno (1990)
Heartbreakers – Vizio di famiglia (2001)
Il cavaliere oscuro (2008)
Il cavaliere oscuro - Il ritorno (2012)
... other text
我尝试重命名文件:
Hooligans (1995).mkv
Hocus Pocus (1993).avi
Ho cercato il tuo nome (2012).avi
Ho cercato il tuo nome (2012).rar
Halloween 2 – Il signore della morte (1981).avi
Highlander 2 – Il ritorno (1990).mkv
Heartbreakers – Vizio di famiglia (2001).avi
Il cavaliere oscuro (2008).mkv
Il cavaliere oscuro - il ritorno (2012).mkv
注意:重命名的文件数与文本文件的行数不一样。在文本文件中可以有 100 行,而要重命名的文件数可以是 50.
有两种方法,但不足以执行我要求的
第一
$movieList = Get-Content movielist.txt
# enumerate all movies
:outer foreach($file in Get-ChildItem "C:\Users\Peter\Desktop\test skript\test2" -File) {
$bn = $file.BaseName
# enumerate all lines of the movies to rename file
foreach($movie in $movieList) {
# if the Base Name is contained in the movie to rename, ie:
# 'Young Devils (1999)' -like '*young Devils*'
if($movie -like "*$bn*") {
# rename the file using the movie + the file's extension, ie:
# Young Devils (1999) + .mkv
Rename-Item -LiteralPath $file.FullName -NewName ($movie + $file.Extension)
# no need to keep comparing this file, if we're here
# we can continue with next file
continue outer
}
}
}
第二名:
$rootFolder = "C:\Users\Peter\Desktop\test skript\test1"
$files = Get-ChildItem -Path $rootFolder -File
$filesNames = Get-Content -Path "$rootFolder\movielist.txt"
foreach ($name in $filesNames)
{
$files | Where-Object -FilterScript {
$name -match [Regex]::Escape($_.BaseName)
} | ForEach-Object -Process {
$ext = $_.Extension
Rename-Item -LiteralPath $_.FullName -NewName "$name$ext" -EA 0
}
}
关于如何重命名示例文件的任何想法?
除了制作电影名称和年份的数组外,这里没有花哨的正则表达式
$filmTextList = @()
get-content -path $rootFolder\movielist.txt | %{$filmTextList += [PSCustomObject]@{Name=($_ -split "(\(\d{4}\))")[0];Year=($_ -split "(\(\d{4}\))")[1]}}
$filmFiles = get-childitem -path C:\Users\Peter\Desktop\test skript\test1
foreach ($film in $filmTextList){
try{
$matchedFilm = Get-Item ([WildcardPattern]::Escape($filmFiles.FullName -match $film.Name))
Rename-Item -LiteralPath $matchedFilm.FullName -NewName "$($film.Name) $($film.Year)$($matchedFilm.Extension)" -ErrorAction SilentlyContinue
}catch{}
}
否则这是您第二次尝试的工作版本:
$rootFolder = "C:\Users\Peter\Desktop\test skript\test1"
$files = Get-ChildItem -Path $rootFolder -File
$filmTextList = @()
get-content -path $rootFolder\movielist.txt | %{$filmTextList += [PSCustomObject]@{Name=($_ -split "(\(\d{4}\))")[0];Year=($_ -split "(\(\d{4}\))")[1]}}
foreach ($film in $filmTextList)
{
$files | Where-Object {
$_.BaseName -match $film.name
} | ForEach-Object {
$ext = $_.Extension
Rename-Item -LiteralPath $_.FullName -NewName "$($film.name)$($film.year)$ext" -EA 0
}
}
我冒昧地使用了你的长长的文件列表和你的 previous question 中的 'movielist.txt',因为它显示名称中有很多额外的字符,使事情变得复杂..
不仅所需名称中的 (year)
,而且某些文件的名称中有点而不是空格,non-ascii 连字符 (en-dashes) 等
做你想做的事你需要
- 创建一个标题哈希表来存储 movielist.tst 文件中的实际值作为值,但也有一个 cleaned-up 版本来与
进行比较
- 用额外的 属性(我称之为 'SearchName')扩展文件数组中的每个 FileInfo object,它存储实际文件的 BaseName 的 cleaned-up 版本以进行比较反对。
$titles = Get-Content -Path 'D:\Test\movielist.txt' -Encoding UTF8 | Select-Object -Unique
# first create a Hashtable with searchable (cleaned-up) titles and the actual title you want as filename
$titleMap = @{}
foreach ($title in $titles) {
# remove everything after a square bracket, remove the year in between brackets,
# remove all non-ascii characters and trim trailing spaces
$search = ($title -replace '(\(\d{4}\)|\[.*|\s*)$' -replace '[^\x00-\x7F]+' -replace '\.|\s+', ' ').Trim()
$titleMap[$search] = $title
}
# next, get an array of these search titels, sorted on Length reversed
# to avoid bad renames on ambiguous names like 'Il cavaliere oscuro' and 'Il cavaliere oscuro - Il ritorno'
$searchTitles = $titleMap.Keys | Sort-Object Length -Descending
# get the list of files in the foler
$files = Get-ChildItem -LiteralPath 'D:\Test' -File -Exclude 'movielist.txt'
foreach ($file in $files) {
$search = ($file.BaseName -replace '(\(\d{4}\)|\[.*|\s*)$' -replace '[^\x00-\x7F]+' -replace '\.|\s+', ' ').Trim()
# extend each object with a cleaned-up searchable name
$file | Add-Member -MemberType NoteProperty -Name 'SearchName' -Value $search
}
# now loop through the search titles and try to find matching filenames from the files
foreach ($title in $searchTitles) {
$files | Where-Object { $_.SearchName -like "*$title*" } | ForEach-Object {
# use '-ErrorAction SilentlyContinue' to avoid errors on files that have already been renamed
Rename-Item -LiteralPath $_.FullName -NewName ('{0}{1}' -f $titleMap[$title], $_.Extension) -ErrorAction SilentlyContinue
}
}
- 来自 movietext.txt 的标题说
Highlander 2 – Il ritorno (1990)
,但文件名只是 Highlander 2 1080p.mkv
。要进行匹配,您还需要在影片文本文件中添加 Highlander 2
。
- 来自 movietext.txt 的标题是
Halloween 2 – Il signore della morte (1981)
,但文件名是 Halloween 2 - Il Signore Della Morte.avi
。同样,在文本文件中,您使用 En-Dash
而不是普通的连字符。
- 来自 movietext.txt 的标题说
Heartbreakers – Vizio di famiglia (2001)
有一个 En-dash 而不是文件名 Heartbreakers - Vizio di famiglia.avi
的普通连字符,所以它们不匹配。
也许,因为您似乎是在像 Word 这样自动使用印刷字形而不是直接字符的文字编辑器中创建 movietext.txt,更好的解决方案是在脚本之上使用辅助函数:
function Get-ComparableName ([string]$Name) {
$Name -replace '(\(\d{4}\)|\[.*|\s*)$' -replace # remove anything after (and including) a square open bracket and the year in brackets
'\.|\s+', ' ' -creplace # replace dots into spaces and normalize spaces
'[\u201C\u201D\u201E\u201F\u2033\u2036]', '"' -creplace # replace double-quote glyphs into straight quotes
"[\u2018\u2019\u201A\u201B\u2032\u2035]", "'" -replace # replace single-quote glyphs into straight quotes
'[\p{Pd}\u2212]','-' -replace # replace dash-like glyphs into a straight hyphen
'([^\x00-\x7F]|\p{Cf})+' # remove non-ascii and invisible control characters
}
并像这样使用它:
foreach ($title in $titles) {
$search = (Get-ComparableName $title).Trim()
$titleMap[$search] = $title
}
再往下一点:
foreach ($file in $files) {
$search = (Get-ComparableName $file.BaseName).Trim()
# extend each object with a cleaned-up searchable name
$file | Add-Member -MemberType NoteProperty -Name 'SearchName' -Value $search
}
关于文件Highlander 2 1080p.mkv
,你需要在你的movielist.txt文件中添加一个标题Highlander 2 (1990)
,否则匹配不上..
我有一些这样的文件
Hooligans (BDrip (1080).mkv
Hocus Pocus [DIVX - ITA] - Walt Disney - HQ-.avi
Ho Cercato Il Tuo Nome h265.avi
Ho Cercato Il Tuo Nome 720.rar
Halloween 2 - Il Signore Della Morte.avi
Highlander 2 1080p.mkv
Heartbreakers - Vizio di famiglia.avi
Il cavaliere oscuro.mkv
Il cavaliere oscuro - il ritorno 1080p.mkv
在同一目录中,我有一个文本文件 (movielist.txt
),它的格式总是这样:name + year.
年份始终来自 19**-20**
并且在方括号
Hooligans (1995)
Hocus Pocus (1993)
Ho cercato il tuo nome (2012)
Halloween 2 – Il signore della morte (1981)
Highlander 2 – Il ritorno (1990)
Heartbreakers – Vizio di famiglia (2001)
Il cavaliere oscuro (2008)
Il cavaliere oscuro - Il ritorno (2012)
... other text
我尝试重命名文件:
Hooligans (1995).mkv
Hocus Pocus (1993).avi
Ho cercato il tuo nome (2012).avi
Ho cercato il tuo nome (2012).rar
Halloween 2 – Il signore della morte (1981).avi
Highlander 2 – Il ritorno (1990).mkv
Heartbreakers – Vizio di famiglia (2001).avi
Il cavaliere oscuro (2008).mkv
Il cavaliere oscuro - il ritorno (2012).mkv
注意:重命名的文件数与文本文件的行数不一样。在文本文件中可以有 100 行,而要重命名的文件数可以是 50.
有两种方法,但不足以执行我要求的
第一
$movieList = Get-Content movielist.txt
# enumerate all movies
:outer foreach($file in Get-ChildItem "C:\Users\Peter\Desktop\test skript\test2" -File) {
$bn = $file.BaseName
# enumerate all lines of the movies to rename file
foreach($movie in $movieList) {
# if the Base Name is contained in the movie to rename, ie:
# 'Young Devils (1999)' -like '*young Devils*'
if($movie -like "*$bn*") {
# rename the file using the movie + the file's extension, ie:
# Young Devils (1999) + .mkv
Rename-Item -LiteralPath $file.FullName -NewName ($movie + $file.Extension)
# no need to keep comparing this file, if we're here
# we can continue with next file
continue outer
}
}
}
第二名:
$rootFolder = "C:\Users\Peter\Desktop\test skript\test1"
$files = Get-ChildItem -Path $rootFolder -File
$filesNames = Get-Content -Path "$rootFolder\movielist.txt"
foreach ($name in $filesNames)
{
$files | Where-Object -FilterScript {
$name -match [Regex]::Escape($_.BaseName)
} | ForEach-Object -Process {
$ext = $_.Extension
Rename-Item -LiteralPath $_.FullName -NewName "$name$ext" -EA 0
}
}
关于如何重命名示例文件的任何想法?
除了制作电影名称和年份的数组外,这里没有花哨的正则表达式
$filmTextList = @()
get-content -path $rootFolder\movielist.txt | %{$filmTextList += [PSCustomObject]@{Name=($_ -split "(\(\d{4}\))")[0];Year=($_ -split "(\(\d{4}\))")[1]}}
$filmFiles = get-childitem -path C:\Users\Peter\Desktop\test skript\test1
foreach ($film in $filmTextList){
try{
$matchedFilm = Get-Item ([WildcardPattern]::Escape($filmFiles.FullName -match $film.Name))
Rename-Item -LiteralPath $matchedFilm.FullName -NewName "$($film.Name) $($film.Year)$($matchedFilm.Extension)" -ErrorAction SilentlyContinue
}catch{}
}
否则这是您第二次尝试的工作版本:
$rootFolder = "C:\Users\Peter\Desktop\test skript\test1"
$files = Get-ChildItem -Path $rootFolder -File
$filmTextList = @()
get-content -path $rootFolder\movielist.txt | %{$filmTextList += [PSCustomObject]@{Name=($_ -split "(\(\d{4}\))")[0];Year=($_ -split "(\(\d{4}\))")[1]}}
foreach ($film in $filmTextList)
{
$files | Where-Object {
$_.BaseName -match $film.name
} | ForEach-Object {
$ext = $_.Extension
Rename-Item -LiteralPath $_.FullName -NewName "$($film.name)$($film.year)$ext" -EA 0
}
}
我冒昧地使用了你的长长的文件列表和你的 previous question 中的 'movielist.txt',因为它显示名称中有很多额外的字符,使事情变得复杂..
不仅所需名称中的 (year)
,而且某些文件的名称中有点而不是空格,non-ascii 连字符 (en-dashes) 等
做你想做的事你需要
- 创建一个标题哈希表来存储 movielist.tst 文件中的实际值作为值,但也有一个 cleaned-up 版本来与 进行比较
- 用额外的 属性(我称之为 'SearchName')扩展文件数组中的每个 FileInfo object,它存储实际文件的 BaseName 的 cleaned-up 版本以进行比较反对。
$titles = Get-Content -Path 'D:\Test\movielist.txt' -Encoding UTF8 | Select-Object -Unique
# first create a Hashtable with searchable (cleaned-up) titles and the actual title you want as filename
$titleMap = @{}
foreach ($title in $titles) {
# remove everything after a square bracket, remove the year in between brackets,
# remove all non-ascii characters and trim trailing spaces
$search = ($title -replace '(\(\d{4}\)|\[.*|\s*)$' -replace '[^\x00-\x7F]+' -replace '\.|\s+', ' ').Trim()
$titleMap[$search] = $title
}
# next, get an array of these search titels, sorted on Length reversed
# to avoid bad renames on ambiguous names like 'Il cavaliere oscuro' and 'Il cavaliere oscuro - Il ritorno'
$searchTitles = $titleMap.Keys | Sort-Object Length -Descending
# get the list of files in the foler
$files = Get-ChildItem -LiteralPath 'D:\Test' -File -Exclude 'movielist.txt'
foreach ($file in $files) {
$search = ($file.BaseName -replace '(\(\d{4}\)|\[.*|\s*)$' -replace '[^\x00-\x7F]+' -replace '\.|\s+', ' ').Trim()
# extend each object with a cleaned-up searchable name
$file | Add-Member -MemberType NoteProperty -Name 'SearchName' -Value $search
}
# now loop through the search titles and try to find matching filenames from the files
foreach ($title in $searchTitles) {
$files | Where-Object { $_.SearchName -like "*$title*" } | ForEach-Object {
# use '-ErrorAction SilentlyContinue' to avoid errors on files that have already been renamed
Rename-Item -LiteralPath $_.FullName -NewName ('{0}{1}' -f $titleMap[$title], $_.Extension) -ErrorAction SilentlyContinue
}
}
- 来自 movietext.txt 的标题说
Highlander 2 – Il ritorno (1990)
,但文件名只是Highlander 2 1080p.mkv
。要进行匹配,您还需要在影片文本文件中添加Highlander 2
。 - 来自 movietext.txt 的标题是
Halloween 2 – Il signore della morte (1981)
,但文件名是Halloween 2 - Il Signore Della Morte.avi
。同样,在文本文件中,您使用En-Dash
而不是普通的连字符。 - 来自 movietext.txt 的标题说
Heartbreakers – Vizio di famiglia (2001)
有一个 En-dash 而不是文件名Heartbreakers - Vizio di famiglia.avi
的普通连字符,所以它们不匹配。
也许,因为您似乎是在像 Word 这样自动使用印刷字形而不是直接字符的文字编辑器中创建 movietext.txt,更好的解决方案是在脚本之上使用辅助函数:
function Get-ComparableName ([string]$Name) {
$Name -replace '(\(\d{4}\)|\[.*|\s*)$' -replace # remove anything after (and including) a square open bracket and the year in brackets
'\.|\s+', ' ' -creplace # replace dots into spaces and normalize spaces
'[\u201C\u201D\u201E\u201F\u2033\u2036]', '"' -creplace # replace double-quote glyphs into straight quotes
"[\u2018\u2019\u201A\u201B\u2032\u2035]", "'" -replace # replace single-quote glyphs into straight quotes
'[\p{Pd}\u2212]','-' -replace # replace dash-like glyphs into a straight hyphen
'([^\x00-\x7F]|\p{Cf})+' # remove non-ascii and invisible control characters
}
并像这样使用它:
foreach ($title in $titles) {
$search = (Get-ComparableName $title).Trim()
$titleMap[$search] = $title
}
再往下一点:
foreach ($file in $files) {
$search = (Get-ComparableName $file.BaseName).Trim()
# extend each object with a cleaned-up searchable name
$file | Add-Member -MemberType NoteProperty -Name 'SearchName' -Value $search
}
关于文件Highlander 2 1080p.mkv
,你需要在你的movielist.txt文件中添加一个标题Highlander 2 (1990)
,否则匹配不上..