使用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 } } }
核心逻辑说明
- 文件夹创建:遍历所有订阅信息TXT文件,以
文件名(不含后缀)为名称创建子文件夹,自动跳过已存在的文件夹 - 报告迁移:针对每个TXT文件,导入Output中的总报告CSV,筛选出该文件内订阅的记录,追加到对应文件夹的CSV中;重复运行时会自动将新内容追加到已有文件,不会覆盖原有数据
- 原脚本优化:将
Select-Object创建对象改为更高效的[PSCustomObject],添加-NoTypeInformation避免CSV生成冗余类型行,用Out-Null屏蔽不必要的Azure上下文切换输出
内容的提问来源于stack exchange,提问作者Saurabh
相关产品推荐
相关产品推荐

