PowerShell 脚本用于检查目录中所有文件夹的名称格式并在每个文件夹中创建子文件夹

PowerShell 脚本用于检查目录中所有文件夹的名称格式并在每个文件夹中创建子文件夹

我有一个主文件夹,其中包含许多文件夹,其名称格式为:大写字母和四个数字(A4431)。我尝试编写的 PowerShell 脚本需要遍历主文件夹中的所有文件夹并检查它们的名称格式是否正确,如果不正确则进行更改。之后,它需要在我的主文件夹中的每个文件夹中创建一个子文件夹结构。子文件夹结构由 4 个文件夹组成,其中一个文件夹有自己的子文件夹。子文件夹结构的名称始终相同。最终结果应如下所示:

Main Folder
 **-A4431**
  -Customers
  -Supplier
  -Orders
    -Sub Folder1
    -Sub Folder2
  -Items
 **-C1131**
  -Customers
  -Supplier
  -Orders
    -Sub Folder1
    -Sub Folder2
  -Items
...

这是我目前所做的,但作用不大。任何帮助都将不胜感激!

#Main directory 
$root = "C:\Work files\Test\Main folder"

#Folder name example (A3234)
$pattern = "^([a-zA-Z]){1}\d{4}"

#Subfolder structure needed to be created in each folder
$folders_names = "Customers","Supplier","Orders","Items"

#Get all folders in $root
$dirs = Get-ChildItem $root | Where-Object {$_.Attributes -eq "Directory"}

#loop through all folders in root and check if they have the right name format and change it if necessary
ForEach ($dir in $dirs)
{
    if(!$dir -match $pattern){
        $newName = '{0}{1}' -f ($_.BaseName -replace '([a-zA-Z]){1}\d{4}') 
        $_ | Rename-Item -NewName $newName -Force 
    }
    #create subfolders in each folder in $root
    ForEach ($name in $folder_names){
        New-item -path "$root\$dir" -Name $name -Type 'directory'
    }
}

根据你的建议进行编辑

这是问题的当前状态。我正在尝试生成一个随机文件夹名称,我将使用该名称替换每个与模式不匹配的文件夹的文件夹名称。

$regex = "^([A-Z]){1}\d{4}"
$randomNr = Get-Random -Minimum 1000 -Maximum 9999
$randomLetter = @("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P")

Get-ChildItem -Path C:\WorkFiles\Test\MainFolder | 
ForEach-Object {
    If ($PSItem.BaseName -notmatch '^([a-zA-Z]){1}\d{4}')
    {"The folder named $($PSItem.BaseName) is not valid. Changing folder name"
      $newName = $randomLetter + $randomNr
      Rename-Item $PSItem.BaseName -NewName $newName.ToString() -WhatIf
    }
    
}

我收到以下错误:

Renaming object: Renaming is not possible because the element does not exist under "v77".
In line: 10 characters: 7
+ Rename item $ PSItem.BaseName -NewName $ newName.ToString () -Was ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~ ~~~~~~~~~~~~~~~~
      + CategoryInfo: InvalidOperation: (:) [Rename-Item], PSInvalidOperationException
      + FullyQualifiedErrorId: InvalidOperation, Microsoft.PowerShell.Commands.RenameItemCommand

我的 MainFolder 中的文件夹结构如下所示。文件夹 v77 应该重命名以匹配模式 C####。关于如何正确完成此操作的任何想法。我非常感谢迄今为止的答案! 测试 MainFolder 内的文件夹结构

答案1

您的帖子只是让我们不得不做出假设。

通常,为了限制/消除混淆,请将您的用例分解为几个步骤,并一次执行一个步骤,以确保在转到下一个步骤之前获得您所期望的结果。

*** 步骤 1 - 读取目录树并验证文件夹名称 ***

如果你的树是这样的:

虚拟文件夹树

Clear-Host

Get-ChildItem -Path C:\WorkFiles\Test\MainFolder | 
ForEach-Object {
    If ($PSItem.BaseName -match '^([a-zA-Z]){1}\d{4}')
    {"The folder named $($PSItem.BaseName) is valid. Processing folder tree"}
    Else {Write-Warning -Message "The folder named $($PSItem.BaseName) is not valid. Updating folder tree."}
}
# Results
<#
WARNING: The folder named 56U87 is not valid. Updating folder tree.
WARNING: The folder named 9999d is not valid. Updating folder tree.
The folder A4431 is named valid. Processing folder tree
The folder B1234 is named valid. Processing folder tree
The folder C1131 is named valid. Processing folder tree
WARNING: The folder Test is not valid. Updating folder tree.
#>

因此,正如您所见,您的第一步是值得怀疑的。因为您说所有文件夹名称都应具有特定的构造,如果不是,则更改它们。把它们改成什么?如果它们不符合分类法,您怎么知道它们是什么以及要将它们改成什么,以便它们不会与已经存在的重复?

如何修复“测试”文件夹或其他文件夹?您最终必须查看所有文件夹,获取所有名称,然后决定如何命名以避免名称冲突。

如果您说所有文件夹名称都将是这样的......

'^([a-zA-Z]){1}\d{4}'

...那么这也意味着解析不匹配的字符串并移动内容、大写内容或完全重命名。

因此,除非你巩固这一点,否则其余的事情都是没有意义的。

*** 第 2 步 创建子文件夹 ***

Clear-Host

Get-ChildItem -Path 'C:\WorkFiles\Test\MainFolder' | 
ForEach-Object {
    If ($PSItem.BaseName -match '^([a-zA-Z]){1}\d{4}' )
    {
        $ParentFolder = $PSItem.FullName
        "The folder named $($PSItem.BaseName) is valid. Processing folder tree"
        'Customers','Supplier','Orders','Items' | 
        ForEach {New-Item -Path $ParentFolder -Name $PSItem -ItemType Directory -WhatIf}
    }
    Else {Write-Warning -Message "The folder named $($PSItem.BaseName) is not valid. Updating folder tree."}
}

Get-ChildItem -Path 'C:\WorkFiles\Test\MainFolder' -Recurse
# Results
<#
WARNING: The folder named 56U87 is not valid. Updating folder tree.
WARNING: The folder named 9999d is not valid. Updating folder tree.
The folder named A4431 is valid. Processing folder tree
What if: Performing the operation "Create Directory" on target "Destination: C:\WorkFiles\Test\MainFolder\A4431\Customers".
What if: Performing the operation "Create Directory" on target "Destination: C:\WorkFiles\Test\MainFolder\A4431\Supplier".
What if: Performing the operation "Create Directory" on target "Destination: C:\WorkFiles\Test\MainFolder\A4431\Orders".
What if: Performing the operation "Create Directory" on target "Destination: C:\WorkFiles\Test\MainFolder\A4431\Items".
The folder named B1234 is valid. Processing folder tree
...
#>

*** 步骤 3 仅为子文件夹 Orders 创建孙文件夹 ***

Clear-Host

Get-ChildItem -Path 'C:\WorkFiles\Test\MainFolder' | 
ForEach-Object {
    If ($PSItem.BaseName -match '^([a-zA-Z]){1}\d{4}' )
    {
        $ParentFolder = $PSItem.FullName
        "The folder named $($PSItem.BaseName) is valid. Processing folder tree"
        'Customers','Supplier','Orders','Items' | 
        ForEach {
            New-Item -Path $ParentFolder -Name $PSItem -ItemType Directory -WhatIf

            $GrandChildFolder = "$ParentFolder\$PSItem"
        
            If ($GrandChildFolder -match 'Orders')
            {
                1..2 | 
                ForEach-Object {New-Item -Path $GrandChildFolder  -Name "Folder$PSItem" -ItemType Directory -WhatIf}
            }
        }
    }
    Else {Write-Warning -Message "The folder named $($PSItem.BaseName) is not valid. Updating folder tree."}
}

Get-ChildItem -Path 'C:\WorkFiles\Test\MainFolder' -Recurse
# Results
<#
WARNING: The folder named 56U87 is not valid. Updating folder tree.
WARNING: The folder named 9999d is not valid. Updating folder tree.
The folder named A4431 is valid. Processing folder tree
What if: Performing the operation "Create Directory" on target "Destination: C:\WorkFiles\Test\MainFolder\A4431\Customers".
What if: Performing the operation "Create Directory" on target "Destination: C:\WorkFiles\Test\MainFolder\A4431\Supplier".
What if: Performing the operation "Create Directory" on target "Destination: C:\WorkFiles\Test\MainFolder\A4431\Orders".
What if: Performing the operation "Create File" on target "Destination: C:\WorkFiles\Test\MainFolder\A4431\Orders\Folder1".
What if: Performing the operation "Create File" on target "Destination: C:\WorkFiles\Test\MainFolder\A4431\Orders\Folder2".
What if: Performing the operation "Create Directory" on target "Destination: C:\WorkFiles\Test\MainFolder\A4431\Items".
The folder named B1234 is valid. Processing folder tree
...
WARNING: The folder named Test is not valid. Updating folder tree.
#>

更新-根据我上次的评论

如果您绝对确定分类法始终是C####。那么只需进行批量重命名即可。

Clear-Host

Get-ChildItem -Path 'C:\WorkFiles\Test\MainFolder'
# Results
<#
    Directory: C:\WorkFiles\Test\MainFolder


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         5/19/2021   2:59 PM                A4431
d-----         5/19/2021   3:00 PM                B1234
d-----         5/19/2021   3:00 PM                C1131
d-----         5/19/2021   3:00 PM                d9999
d-----         5/19/2021   3:02 PM                u5687
#>

Clear-Host

Get-ChildItem 'C:\WorkFiles\Test\MainFolder' -Directory | 
Rename-Item -NewName {($TempName = "_$($PSItem.BaseName.ToUpper())")}

Get-ChildItem 'C:\WorkFiles\Test\MainFolder' -Directory | 
Rename-Item -NewName {$PSItem.BaseName -replace '_',''}


Get-ChildItem -Path 'C:\WorkFiles\Test\MainFolder'
# Results
<#
    Directory: C:\WorkFiles\Test\MainFolder


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         5/19/2021   2:59 PM                A4431
d-----         5/19/2021   3:00 PM                B1234
d-----         5/19/2021   3:00 PM                C1131
d-----         5/19/2021   3:00 PM                D9999
d-----         5/19/2021   3:02 PM                U5687
#>

其余代码相同。

Clear-Host

Get-ChildItem -Path 'C:\WorkFiles\Test\MainFolder' | 
ForEach-Object {
    $ParentFolder = $PSItem.FullName

    'Customers','Supplier','Orders','Items' | 
    ForEach {
        New-Item -Path $ParentFolder -Name $PSItem -ItemType Directory

        $GrandChildFolder = "$ParentFolder\$PSItem"
       
        If ($PSItem -match 'Orders')
        {
            1..2 | 
            ForEach-Object {New-Item -Path $GrandChildFolder  -Name "Folder$PSItem" -ItemType Directory}
        }
    }
}

更新 - 根据我们的后续评论

以下是我试图提供启发的想法。请注意,这只是其中一种方法。众所周知,PowerShell 有许多方法可以实现 X 或 Y,其中一些方法比其他方法更优雅。下面的方法还不够完善,但确实有所变化。因此,您需要根据自己的用例进行调整。

Clear-Host
$Increment = 1

Get-ChildItem -Path 'C:\WorkFiles\Test\MainFolder' -Directory | 
ForEach-Object{
    $FolderName       = $PSItem
    $FolderNameLength = $PSItem.BaseName.Length

    switch ($FolderNameLength)
    {
        5        
        {
            $FolderName | 
            Rename-Item -NewName $($FolderName.Name).ToUpper() -WhatIf
        }
        Default  
        {
            If ($FolderName.Name.Length -lt 5)
            {
                If(-Not (Test-Path -Path "$($folderName.Parent.FullName)\$($($FolderName.Name).PadRight(5, '0').ToUpper())))"))
                {Rename-Item -Path $FolderName.FullName -NewName $($FolderName.Name).PadRight(5, '0').ToUpper() -WhatIf}
            }
            Else
            {
                If((Test-Path -Path "$($folderName.Parent.FullName)\$($($FolderName.Name.Substring(0,5).ToUpper())))"))
                {$FolderName.Name.Substring(0,5).ToUpper()}
                Else {Rename-Item -Path $FolderName.FullName -NewName ($FolderName.Name.Substring(0,5).ToUpper() -replace $FolderName.Name.Substring(1,4), ([string][int]$FolderName.Name.Substring(1,3) + ($Increment++))) -WhatIf}
            }
        }
    }
}
# Results
<#
What if: Performing the operation "Rename Directory" on target "Item: C:\WorkFiles\Test\MainFolder\A4431 Destination: C:\WorkFiles\Test\MainFolder\A4431".
What if: Performing the operation "Rename Directory" on target "Item: C:\WorkFiles\Test\MainFolder\B1234 Destination: C:\WorkFiles\Test\MainFolder\B1234".
What if: Performing the operation "Rename Directory" on target "Item: C:\WorkFiles\Test\MainFolder\C1131 Destination: C:\WorkFiles\Test\MainFolder\C1131".
What if: Performing the operation "Rename Directory" on target "Item: C:\WorkFiles\Test\MainFolder\d9999 Destination: C:\WorkFiles\Test\MainFolder\D9999".
What if: Performing the operation "Rename Directory" on target "Item: C:\WorkFiles\Test\MainFolder\u5687 Destination: C:\WorkFiles\Test\MainFolder\U5687".
What if: Performing the operation "Rename Directory" on target "Item: C:\WorkFiles\Test\MainFolder\v77 Destination: C:\WorkFiles\Test\MainFolder\V7700".
What if: Performing the operation "Rename Directory" on target "Item: C:\WorkFiles\Test\MainFolder\v778 Destination: C:\WorkFiles\Test\MainFolder\V7780".
What if: Performing the operation "Rename Directory" on target "Item: C:\WorkFiles\Test\MainFolder\X10000 Destination: C:\WorkFiles\Test\MainFolder\X1001".
What if: Performing the operation "Rename Directory" on target "Item: C:\WorkFiles\Test\MainFolder\x100000 Destination: C:\WorkFiles\Test\MainFolder\X1002".
What if: Performing the operation "Rename Directory" on target "Item: C:\WorkFiles\Test\MainFolder\z123456789 Destination: C:\WorkFiles\Test\MainFolder\Z1233".
What if: Performing the operation "Rename Directory" on target "Item: C:\WorkFiles\Test\MainFolder\z1234567890 Destination: C:\WorkFiles\Test\MainFolder\Z1234".
#>

以下是处理上述用例的重构:

请记住,只在测试环境中运行从其他人那里获得的代码或利用-WhatIf and or -Confirm

Clear-Host

$WhatIfPreference      = $true
$ErrorActionPreference = 'SilentlyContinue'
$SourcePath            = 'C:\WorkFiles\Test\MainFolder'
$Increment             = 1

Get-ChildItem -Path $SourcePath  -Directory | 
ForEach-Object {
    If ($PSItem.BaseName.Length -eq 5)
    {
        $TempName = ($PSItem     | 
        Rename-Item -NewName {("_$($PSItem.BaseName.ToUpper())")} -PassThru)

        Get-Item -Path $TempName | 
        Rename-Item -NewName {$PSItem.FullName -replace '_',''}    
    }


    If ($PSItem.BaseName.Length -lt 5)
    {Rename-Item -Path $PSItem.FullName -NewName $($PSItem.BaseName).PadRight(5,'0').ToUpper()}


    If ($PSItem.BaseName.Length -gt 5)
    {
        Rename-Item -Path $PSItem.FullName -NewName $(
            $(($PSItem.BaseName.Substring(0,5)).ToUpper()) -replace 
            '\d{4}', ($($PSItem.BaseName.Substring(1,3) + $Increment++))
        )
    }
}

$WhatIfPreference      = $false
$ErrorActionPreference = 'Continue'

更新 --- 或者对所有这些进行随机重命名重构,以强制执行您的分类法,而不管原始名称如何

Clear-Host

$WhatIfPreference      = $true
$ErrorActionPreference = 'SilentlyContinue'
$Increment = 1

Get-ChildItem -Path 'C:\WorkFiles\Test\MainFolder' -Directory | 
ForEach-Object {
    $NewFolderName = (([char[]](65..90))  | Get-Random -Count 1) + 
                     (([char[]]((48..57)) | Get-Random -Count 4) -join '')

    If ($PSItem.BaseName -cnotmatch ($PSItem.BaseName.ToUpper()))
    {Rename-Item $PSItem.FullName -NewName ($PSItem.BaseName -creplace $PSItem.BaseName, $NewFolderName)}
    Else
    {
        Rename-Item -Path $PSItem.FullName -NewName $(
            $(($PSItem.BaseName.Substring(0,5)).ToUpper()) -replace 
            '\d{4}', ($($NewFolderName.Substring(1,3) + $Increment++))
        )    
    }
}

$WhatIfPreference      = $false
$ErrorActionPreference = 'Continue'
# Results
<#
What if: Performing the operation "Rename Directory" on target "Item: C:\WorkFiles\Test\MainFolder\A4431 Destination: C:\WorkFiles\Test\MainFolder\A6121".
What if: Performing the operation "Rename Directory" on target "Item: C:\WorkFiles\Test\MainFolder\B1234 Destination: C:\WorkFiles\Test\MainFolder\B5102".
What if: Performing the operation "Rename Directory" on target "Item: C:\WorkFiles\Test\MainFolder\C1131 Destination: C:\WorkFiles\Test\MainFolder\C5233".
What if: Performing the operation "Rename Directory" on target "Item: C:\WorkFiles\Test\MainFolder\d9999 Destination: C:\WorkFiles\Test\MainFolder\X7184".
What if: Performing the operation "Rename Directory" on target "Item: C:\WorkFiles\Test\MainFolder\u5687 Destination: C:\WorkFiles\Test\MainFolder\C4251".
What if: Performing the operation "Rename Directory" on target "Item: C:\WorkFiles\Test\MainFolder\v77 Destination: C:\WorkFiles\Test\MainFolder\B6340".
What if: Performing the operation "Rename Directory" on target "Item: C:\WorkFiles\Test\MainFolder\v778 Destination: C:\WorkFiles\Test\MainFolder\P1738".
What if: Performing the operation "Rename Directory" on target "Item: C:\WorkFiles\Test\MainFolder\X10000 Destination: C:\WorkFiles\Test\MainFolder\X3764".
What if: Performing the operation "Rename Directory" on target "Item: C:\WorkFiles\Test\MainFolder\x100000 Destination: C:\WorkFiles\Test\MainFolder\D1845".
What if: Performing the operation "Rename Directory" on target "Item: C:\WorkFiles\Test\MainFolder\x100003 Destination: C:\WorkFiles\Test\MainFolder\G5641".
What if: Performing the operation "Rename Directory" on target "Item: C:\WorkFiles\Test\MainFolder\X100004 Destination: C:\WorkFiles\Test\MainFolder\X9685".
What if: Performing the operation "Rename Directory" on target "Item: C:\WorkFiles\Test\MainFolder\z123456789 Destination: C:\WorkFiles\Test\MainFolder\S7638".
What if: Performing the operation "Rename Directory" on target "Item: C:\WorkFiles\Test\MainFolder\Z1234567890 Destination: C:\WorkFiles\Test\MainFolder\Z6916".
#>

相关内容