You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用PowerShell按文件名创建文件夹并迁移Azure订阅报告文件

解决方案

功能实现说明

针对需求,我们将现有脚本扩展为先生成统一报告,再按订阅信息TXT文件名拆分迁移的逻辑,同时支持重复运行时自动追加内容到已存在的对应文件夹。

修改后的完整脚本

# 基础路径配置
$subscriptionFilesFolder = 'C:\Scrpting\Subscriptions'
$baseOutputFolder = 'C:\Scrpting\Output'
$dateSuffix = (Get-Date).ToString("yyyyMMdd")

# ---------------------- 第一步:生成统一报告(保留原脚本核心逻辑,优化细节) ----------------------
$Files = Get-ChildItem -Path $subscriptionFilesFolder -File | Select-Object -ExpandProperty FullName
$AzSubs = Get-Content -Path $Files

# 生成用户角色报告
ForEach ($AzSub in $AzSubs) {
    Set-AzContext -SubscriptionName $AzSub | Out-Null
    $Userroles = Get-AzRoleAssignment | Where-Object { $_.ObjectType -eq "User" }
    
    Foreach ($User in $Userroles) {
        [PSCustomObject]@{
            DisplayName        = $User.DisplayName
            SignInName         = $User.SignInName
            RoleDefinitionName = $User.RoleDefinitionName
            SubscriptionName   = $AzSub
        } | Export-Csv -Path (Join-Path $baseOutputFolder "UserRoles$dateSuffix.csv") -Append -NoTypeInformation
    }
}

# 生成NSG防火墙规则报告
ForEach ($azSub in $azSubs) {
    Set-AzContext -SubscriptionName $azSub | Out-Null
    $azNsgs = Get-AzNetworkSecurityGroup
    
    $Output = ForEach ($azNsg in $azNsgs) {
        Get-AzNetworkSecurityRuleConfig -NetworkSecurityGroup $azNsg | 
            Select-Object @{label = 'NSG Name'; expression = { $azNsg.Name } },
            @{label = 'NSG Location'; expression = { $azNsg.Location } },
            @{label = 'Rule Name'; expression = { $_.Name } },
            @{label = 'Source'; expression = { $_.SourceAddressPrefix } },
            @{label = 'Source Application Security Group'; expression = { $_.SourceApplicationSecurityGroups.id.Split('/')[-1] } },
            @{label = 'Source Port Range'; expression = { $_.SourcePortRange } },
            Access, Priority, Direction,
            @{label = 'Destination'; expression = { $_.DestinationAddressPrefix } },
            @{label = 'Destination Application Security Group'; expression = { $_.DestinationApplicationSecurityGroups.id.Split('/')[-1] } },
            @{label = 'Destination Port Range'; expression = { $_.DestinationPortRange } },
            @{label = 'Resource Group Name'; expression = { $azNsg.ResourceGroupName } },
            @{label = 'Subscription Name'; expression = { $azSub } }
    }
    $Output | Export-Csv -Path (Join-Path $baseOutputFolder "FirewallRules$dateSuffix.csv") -Append -NoTypeInformation
}

# 生成虚拟机信息报告
ForEach ($AzSub in $AzSubs) {
    Set-AzContext -SubscriptionID $AzSub | Out-Null
    $vms = Get-AzVM
    $nics = Get-AzNetworkInterface | Where-Object { $_.VirtualMachine -ne $null }
    
    ForEach ($nic in $nics) {
        $vm = $vms | Where-Object { $_.Id -eq $nic.VirtualMachine.id }
        $PublicIPAddress = (Az vm list-ip-addresses --name $vm.Name --resource-group $vm.ResourceGroupName | ConvertFrom-Json).virtualMachine.network.publicIpAddresses.ipaddress
        
        [PSCustomObject]@{
            VMName              = $vm.Name
            ResourceGroupName   = $vm.ResourceGroupName
            OS                  = $vm.StorageProfile.osDisk.osType
            PrivateIPAddress    = $nic.IpConfigurations.PrivateIpAddress
            PublicIPAddress     = if ($PublicIPAddress -eq $null) { "Not Assigned" } else { $PublicIPAddress }
            SubscriptionID      = $AzSub
            Status              = ((Get-AzVM -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name -Status).Statuses[1]).code
            NICName             = $nic.Name
        } | Export-Csv -Path (Join-Path $baseOutputFolder "VMInfo$dateSuffix.csv") -Append -NoTypeInformation
    }
}

# ---------------------- 第二步:按TXT文件名拆分迁移报告 ----------------------
$subscriptionFiles = Get-ChildItem -Path $subscriptionFilesFolder -Filter *.txt -File

foreach ($file in $subscriptionFiles) {
    # 创建对应文件夹(不含TXT后缀)
    $targetFolder = Join-Path -Path $baseOutputFolder -ChildPath $file.BaseName
    if (-not (Test-Path -Path $targetFolder)) {
        New-Item -Path $targetFolder -ItemType Directory | Out-Null
    }

    $subscriptionsInFile = Get-Content -Path $file.FullName

    # 迁移用户角色报告
    $srcCsv = Join-Path $baseOutputFolder "UserRoles$dateSuffix.csv"
    if (Test-Path $srcCsv) {
        $filteredRecords = Import-Csv $srcCsv | Where-Object { $subscriptionsInFile -contains $_.SubscriptionName }
        if ($filteredRecords) {
            $targetCsv = Join-Path $targetFolder "UserRoles$dateSuffix.csv"
            $filteredRecords | Export-Csv $targetCsv -Append -NoTypeInformation
        }
    }

    # 迁移NSG规则报告
    $srcCsv = Join-Path $baseOutputFolder "FirewallRules$dateSuffix.csv"
    if (Test-Path $srcCsv) {
        $filteredRecords = Import-Csv $srcCsv | Where-Object { $subscriptionsInFile -contains $_.'Subscription Name' }
        if ($filteredRecords) {
            $targetCsv = Join-Path $targetFolder "FirewallRules$dateSuffix.csv"
            $filteredRecords | Export-Csv $targetCsv -Append -NoTypeInformation
        }
    }

    # 迁移虚拟机信息报告
    $srcCsv = Join-Path $baseOutputFolder "VMInfo$dateSuffix.csv"
    if (Test-Path $srcCsv) {
        $filteredRecords = Import-Csv $srcCsv | Where-Object { $subscriptionsInFile -contains $_.SubscriptionID }
        if ($filteredRecords) {
            $targetCsv = Join-Path $targetFolder "VMInfo$dateSuffix.csv"
            $filteredRecords | Export-Csv $targetCsv -Append -NoTypeInformation
        }
    }
}

核心逻辑说明

  1. 文件夹创建:遍历所有订阅信息TXT文件,以文件名(不含后缀)为名称创建子文件夹,自动跳过已存在的文件夹
  2. 报告迁移:针对每个TXT文件,导入Output中的总报告CSV,筛选出该文件内订阅的记录,追加到对应文件夹的CSV中;重复运行时会自动将新内容追加到已有文件,不会覆盖原有数据
  3. 原脚本优化:将Select-Object创建对象改为更高效的[PSCustomObject],添加-NoTypeInformation避免CSV生成冗余类型行,用Out-Null屏蔽不必要的Azure上下文切换输出

内容的提问来源于stack exchange,提问作者Saurabh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 08:25:27