重命名文件中的多个迭代

时间:2019-03-29 19:09:31

标签: powershell refactoring

我有一个文件夹,其中包含不同数量的文件,格式相同,都是从共享站点批量下载的。

所有下载的文件都使用类似的模式自动命名,但是,这不是我的服务器所需的结束模式。下面的代码可以完成工作,但是看起来很笨拙,我的直觉说,有一种更好的方法可以在文件名上写入多个替换项。请帮我重新编码。

我尝试了多个管道,看来问题出在以下事实:一旦使用第一次迭代将文件重命名,之后的所有引用都将不成立。因此,替换后,我需要为该新迭代创建一个新变量。

$pathToRFIs = 'C:\Users\user\Downloads\*.pdf'
$path2ToRFIs = 'C:\Users\user\Downloads'

$text = [System.Threading.Thread]::CurrentThread.CurrentCulture.TextInfo


$lowerRFIs = gci -path $pathToRFIs -filter *rfi*
$lowerRFIs | ren -newname {"$($text.ToTitleCase($_.BaseName))$($_.Extension)"}

$properRFIs = gci -path $pathToRFIs -filter *rfi*
$properRFIs | ren -newname {$_.name -replace '___',' & '}

$andRFIs = gci -path $pathToRFIs -filter *rfi*
$andRFIs | ren -newname {$_.name -replace '_',' '}

$spaceRFIs = gci -path $pathToRFIs -filter *rfi*
$spaceRFIs | ren -newname {$_.name -replace 'Encinitas Beach Resort-Rfi ','RFI 00'}

$RFIs = gci -path $pathToRFIs  -filter *RFI*
$RFIs | ren -newname {$_.name -replace '^(.*?)-', '$1_'}

$RFIs_ = gci -path $pathToRFIs -filter *RFI*
$RFIs_ | ren -newname {$_.name.substring(0,$_.name.length-17)}

$finalRFIs = gci -path $path2ToRFIs *"RFI 0"*
$finalRFIs | ren -newname {$_.fullname + ".pdf"}

作为参考,我收到的文件如下:

"encinitas beach resort-rfi 31-public water closets-201903221442.pdf"

所需的最终结果名称为:

"RFI 0031_Public Water Closets.pdf"

3 个答案:

答案 0 :(得分:0)

按照建议的Lee_Daily使用ForEach-Object,可以使用正则表达式-match捕获所需文件名的各个部分。 (数字和主题)。

然后,在循环内部执行如下重命名操作:

$pathToRFIs = 'C:\Users\user\Downloads'

Get-ChildItem -Path $pathToRFIs -Filter '*rfi*' -File | ForEach-Object {
    if ($_.BaseName -match '.*rfi\s+(?<number>\d+)-(?<subject>.*)\s*-\d+$') {
        $subject = (Get-Culture).TextInfo.ToTitleCase($matches['subject']) -replace '___',' & ' -replace '_', ' '
        $newName = 'RFI {0:D4}_{1}{2}' -f ([int]$matches['number']), $subject, $_.Extension

        $_ | Rename-Item -NewName $newName -WhatIf
    }
}

如果对结果感到满意,请关闭-WhatIf开关。

使用此文件,encinitas beach resort-rfi 31-public water closets-201903221442.pdf之类的文件将成为
RFI 0031_Public Water Closets.pdf

正则表达式详细信息:

.              # Match any single character that is not a line break character
   *           # Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
rfi            # Match the characters “rfi” literally
\s             # Match a single character that is a “whitespace character” (spaces, tabs, line breaks, etc.)
   +           # Between one and unlimited times, as many times as possible, giving back as needed (greedy)
(?<number>     # Match the regular expression below and capture its match into backreference with name “number”
   \d          # Match a single digit 0..9
      +        # Between one and unlimited times, as many times as possible, giving back as needed (greedy)
)
-              # Match the character “-” literally
(?<subject>    # Match the regular expression below and capture its match into backreference with name “subject”
   .           # Match any single character that is not a line break character
      *        # Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
)
\s             # Match a single character that is a “whitespace character” (spaces, tabs, line breaks, etc.)
   *           # Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
-              # Match the character “-” literally
\d             # Match a single digit 0..9
   +           # Between one and unlimited times, as many times as possible, giving back as needed (greedy)
$              # Assert position at the end of the string (or before the line break at the end of the string, if any)

答案 1 :(得分:0)

答案:是的。请注意,这只是您已经完成的工作的一种转变。通过使用一次对Rename-Item的调用并在foreach上使用ForEach-Object,它的速度也会大大提高。

$text = [System.Threading.Thread]::CurrentThread.CurrentCulture.TextInfo
foreach ($file in Get-ChildItem -Path $Env:USERPROFILE\Downloads\*.pdf -Filter *rfi*) {
    $rename = $text.ToTitleCase($file.BaseName) + $file.Extension
    $rename = $rename -replace '_{3}', ' & ' -replace '_', ' ' -replace 'Encinitas Beach Resort-Rfi ', 'RFI 00'
    $rename = $rename -replace '^(.*?)-', '$1_'
    $rename = $rename.Substring(0, $rename.Length - 17) + '.pdf'
    $file | Rename-Item -NewName $rename
}

一个正则表达式将所有规则都减去大写字母:

$n -replace '.*?-rfi (\d+)-(.*?)-.*', 'RFI $1_$2.pdf'

答案 2 :(得分:0)

  • 没有必要的中间变量
  • 也没有ForEach对象
  • 所有的转化蛋白都可以彼此粘合在一起,这里带有反引号在单独的线上
  • 和结尾的-Whatif仅显示如果发生了什么情况。

## Q:\Test\2019\03\29\SO_55424102.ps1
$pathToRFIs = 'C:\Users\user\Downloads\*.pdf'

$text = [System.Threading.Thread]::CurrentThread.CurrentCulture.TextInfo

Get-ChildItem -Path $pathToRFIs -Filter *rfi* |
    Rename-Item -NewName {($text.ToTitleCase($_.BaseName) `
       -replace '___',' & ' `
       -replace '_',' ' `
       -replace 'Encinitas Beach Resort-Rfi ','RFI 00' `
       -replace '(?<=^[^-]*)-', '_' `
       -replace '-\d{12}$')+$_.Extension} -WhatIf

样本输出(德语区域设置):

WhatIf: Ausführen des Vorgangs "Datei umbenennen" für das 
Ziel "Element: Q:\Test\2019\03\29\encinitas beach resort-rfi 31-public water closets-201903221442.pdf 
         Ziel: Q:\Test\2019\03\29\RFI 0031_Public Water Closets.pdf".

如果输出看起来正常,请删除-WhatIf