Rename azure blob with specific condition - azure

I have a Storage account with Test container and this container contains 24 folders and each folder contains n numbers of blobs. What i want is to rename all the folder and sub blob in Pic 1 to exactly like in Pic 2.
I've used this rename script:
How to rename a blob file using powershell
But above script is useful for one or two blobs plus this script doesn't renames folder(this can be solved by copying the blob to new location) where as in my case i have n blob which i tried to tackle with:
$textinfo = (Get-Culture).TextInfo
$text2=($textinfo.ToTitleCase($text)).Split(" ")
But this is also not helping since it will rename exchangerate to Exchangerate but not to ExchangeRate(and this is the real requirement).
I thought of this:
foreach($file in $text)
{
Get-AzStorageBlob -Container 'test' -Context $storageContext -Blob $text|
Rename-AzStorageBlob -NewName ''
}
But then new name(parameter) i'm not able to make it dynamic. How to approach this?

If you want to rename a blob from exchangerate to ExchangeRate, there is no automatic way for this.
To do that, as Martin mentioned, you'd better have a mapping where you can lookup exchangerate -> ExchangeRate (and also for all other names contain more than one words).
Otherwise, your code doesn't know whether a letter in the new blob name should be uppercase or not.

Modified my code something like this
##Lookup.
$hash = $null
##Hash table with keys in Lowercase and values in Uppercase
$hash = #{...}
##Renaming the files.
$file = $null
$file1 = $null
foreach($file in $text)
{
if($hash.Values -eq $file)
{
Write-Host 'Old name' $file
foreach($file1 in $hash.Values)
{
if($file -eq $file1)
{
Write-Host 'New name' $file1
Get-AzStorageBlob -Container 'test' -Context $storageContext -Blob $file| Rename-AzStorageBlob -NewName $file1
}
}
}
}
So this is working for me.

Related

Parse Excel variables into powershell

I am trying to create a powershell that will grab the varibles from an excel sheet and then add them to the powersehll command.
in the excel sheet i have 3 columns i am interested in the data from (Name , resourcegroup, location)
And then for each line with this i want it to parse into into the varible field for the powershell
I have created the powershell to do what i need but it would be better if it could loop through and pull this as I am just running the command again with different machine info manually added from the excel.
With #Theo Help
I am working with this version of the script now
Import-Csv -Path 'c:\scripts\vmtest.csv' | ForEach-Object {
# combine the VMName with suffix '-Snapshot'
$snapshotName = $vm.name + "-Snapshot"
$SnapshotStorage = "Azure-Snapshots"
$vm = Get-AzVM -ResourceGroupName $_.ResourceGroup -Name $_.Name
# using splatting for better readability
$configParams = #{
SourceUri = $vm.StorageProfile.OsDisk.ManagedDisk.Id
Location = $_.location
CreateOption = 'copy'
}
$snapshot = New-AzSnapshotConfig #configParams
New-AzSnapshot -Snapshot $snapshot -SnapshotName $snapshotname -ResourceGroupName $snapshotstorage
}
If as you have commented, you now have the data stored in a CSV file that might look something like this:
Name,ResourceGroup,Location
PRD-ITM001,SJAVIRTUALMACHINES,uksouth
TST-GRSSQL001,SJAVIRTUALMACHINES,uksouth
it has become very simple to import that data and loop through the records like below:
Import-Csv -Path 'c:\scripts\vmtest.csv' | ForEach-Object {
# combine the VMName with suffix '-Snapshot'
$snapshotName = '{0}-Snapshot' -f $_.Name
$SnapshotStorage = "Azure-Snapshots"
$vm = Get-AzVM -ResourceGroupName $_.ResourceGroup -Name $_.Name
# using splatting for better readability
$configParams = #{
SourceUri = $vm.StorageProfile.OsDisk.ManagedDisk.Id
Location = $_.Location
CreateOption = 'copy'
}
$snapshot = New-AzSnapshotConfig #configParams
New-AzSnapshot -Snapshot $snapshot -SnapshotName $snapshotName -ResourceGroupName $_.ResourceGroup
}
Note that the above code assumes your CSV uses the (default) comma as delimiter character. If in your case this is some other character, append parameter -Delimiter followed by the character the csv uses.
Inside a ForEach-Object {..} loop, the $_ automatic variable references the current record from the csv
I used Splatting for better readability of the code. This helps on cmdlets that take a long list of parameters and eliminates the use of the backtick.
Based on the above shared requirement, we understood that you want to pull the values of ResourceGroupName, VMName from the excel sheet & also you want to use those values in the script further.
Using PSExcel Module, We have written the below PowerShell Script which will pull the ResourceGroupName, VMName from excel & it will run Get-AzVM Cmdlet.
Before running the below PowerShell script , run the below cmdlet Save-Azcontext cmdlet it will saves the current authentication information for use in other PowerShell sessions.
Connect-AzAccount
Save-AzContext -Path C:\test.json
Here is the PowerShell script:
$currentDir = "C:\Program Files\WindowsPowerShell\Modules" ##pass the path of the PSexcel Module
Import-Module $currentDir"\PSExcel"
Import-AzContext -Path C:\test.json ##passing the azcontext file path which was saved earlier
$ExcelFile = "Give here the path of the current folder where scripts are stored"
$objExcel = New-Excel -Path $ExcelFile
$WorkBook = $objExcel|Get-Workbook
ForEach($Worksheet in #($Workbook.Worksheets)){
$totalNoOfRecords = $Worksheet.Dimension.Rows
$totalNoOfItems = $totalNoOfRecords-1
# Declare the starting positions first row and column names
$rowNo,$colResourceGroupName = 1,1
$rowNo,$colVMName = 1,2
if ($totalNoOfRecords -gt 1){
#Loop to get values from excel file
for($i=1;$i -le ($totalNoOfRecords-1);$i++){
$ResourceGroupName=$Worksheet.Cells.Item($rowNo+$i,$colResourceGroupName).Value
$VMName=$Worksheet.Cells.Item($rowNo+$i,$colVMName).Value
Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName |select -Property Name,ResourceGroupName,Location
}
}
}
Here is the sample output for reference:
For more information ,you refer this blog post on How to Read excel file using PSExcel Module in PowerShell.

Create a series of PowerShell variables from Excel to execute in Robocopy

Using the PowerShell module importexcel I have created the variables and the job is running but with a few caveats. The data from the source is dumped into the root of the destination (which is expected based on the variables I've created - which is one of many areas I ask for help).
$dataJob01 = Import-Excel "C:\temp\test.xlsx"
ForEach ($project in $dataJob01){
$source = $($dataJob01.Source)
$destination = $($dataJob01.Destination)
robocopy $source $destination /e /copy:DATU /dcopy:DAT /log:C:\temp\log.txt
}
Is there a way to append the "Folder Name" to the destination variable? Making the $destination = \\server2\share\PROJECTS\304401
Until the issue in problem 1 is solved, problem 2 is irrelevant but ideally I want the job to process 100s of lines below the excel snippet above. Unfortunately, that is failing with the code I've written. It's as if the source and destination are being bunched together vs. being processed on each line. I thought ForEach was appropriate but I'm a noob.
When I run this against multiple lines, I receive no output and the job fails.
Hopefully I'm not going about this the wrong way and someone has some pointers for me.
Is there a way to append the "Folder Name" to the destination variable? Making the $destination = \server2\share\PROJECTS\304401
Here you can use Join-Path which works perfectly for what you need:
$destination = Join-Path $project.Destination -ChildPath $project.'Folder Name'
I've noticed you're using $dataJob01, which is the array you're using to iterate, inside your foreach loop. Try using this instead (I changed the name of the variables, so it helps you understand. $line is exactly that).
$xlsx = Import-Excel "C:\temp\test.xlsx"
ForEach ($line in $xlsx)
{
$source = $line.Source
$destination = Join-Path $line.Destination -ChildPath $line.'Folder Name'
robocopy $source $destination /e /copy:DATU /dcopy:DAT /log:C:\temp\log.txt
}

Automate creating configurations from template and excel

I'm having trouble in automation of a configuration.
I have a template of a configuration and need to change all the hostname (marked as YYY) and IP (marked as XXX(only 3rd octet needs replacement)) according to a list of excel values.
Now I have a list of 100 different sites and IPs and I want to have also 100 different configurations.
A friend suggested to use the following Powershell code but it doesn't any create files..:
$replaceValues = Import-Csv -Path "\\ExcelFile.csv"
$file = "\\Template.txt"
$contents = Get-Content -Path $file
foreach ($replaceValue in $replaceValues)
{
$contents = $contents -replace "YYY", $replaceValue.hostname
$contents = $contents -replace "XXX", $replaceValue.site
Copy-Item $file "$($file.$replaceValue.hostname)"
Set-Content -Path "$($file.$replaceValue.hostname)" -Value $contents
echo "$($file.$replaceValue.hostname)"
}
Your code tries to overwrite the same $contents string in the loop, so if the values are replaced the first time you enter the loop, there won't be any YYY or XXX values to replace left..
You need to keep the template text intact, and create a new copy from the template inside the loop. That copy can then be altered the way you want. Every next iteration wil then start off with a fresh copy of the template.
There is no need to first copy the template text to a new location and then overwrite this file with the new contents. Set-Content is happy to create a new file for you if it does not already exist.
Try
$replaceValues = Import-Csv -Path 'D:\Test\Values.csv'
$template = Get-Content -Path 'D:\Test\Template.txt'
foreach ($item in $replaceValues) {
$content = $template -replace 'YYY', $item.hostname -replace 'XXX', $item.site
$newFile = Join-Path -Path 'D:\Test' -ChildPath ('{0}.txt' -f $item.hostname)
Write-Host "Creating file '$newFile'"
$content | Set-Content -Path $newFile
}

Delete a "folder" in Azure Blob Storage

I would like to delete a folder from the container of my Azure Blob Storage account. This one contains 3 000 000+ files and using Azure Storage Explorer it is a pretty long process (1 000 files/5 min) so I would like to know if it is possible to delete a folder at once.
I am aware there is no "folder" in Azure Blob Storage and it is more a virtual path to access a blob but regarding batch deletion for a huge amount of blobs it is problematic.
Ben I'd recommend using this Powershell script allowing the deletion of 10,000 a time:
This PowerShell script, designed to run in Azure Automatiom, deletes huge number of blobs in a container, by processing them in chunks of 10,000 blobs at a time. When the number of blobs grows beyond a couple of thousands, the usual method of deleting each blob at a time may just get suspended without completing the task.
This could be used to to delete all blobs (when parameter retentionDays is supplied as 0), or certain blobs which has not been modified for the last rententionDays number of days.
Script can be downloaded here: https://gallery.technet.microsoft.com/Delete-large-number-of-97e04976
<#
.Synopsis
Deletes large number of blobs in a container of Storage account, which are older than x days
.DESCRIPTION
This Runbook deletes huge number of blobs in a container, by processing them in chunks of 10,000 blobs at a time. When the number of blobs grow beyond a couple of thousands, the usual method of deleting each blob at a time may just get suspended without completing the task.
.PARAMETER CredentialAssetName
The Credential asset which contains the credential for connecting to subscription
.PARAMETER Subscription
Name of the subscription attached to the credential in CredentialAssetName
.PARAMETER container
Container name from which the blobs are to be deleted
.PARAMETER AzStorageName
The Storage Name to which the container belong to
.PARAMETER retentionDays
Retention days. Blobs older than these many days will be deleted. To delete all, use 0
.NOTES
AUTHOR: Anurag Singh, MSFT
LASTEDIT: March 30, 2016
#>
function delete-blobs
{
param (
[Parameter(Mandatory=$true)]
[String] $CredentialAssetName,
[Parameter(Mandatory=$true)]
[String] $Subscription,
[Parameter(Mandatory=$true)]
[String] $container,
[Parameter(Mandatory=$true)]
[String] $AzStorageName,
[Parameter(Mandatory=$true)]
[Int] $retentionDays
)
$Cred = Get-AutomationPSCredential -Name $CredentialAssetName
$Account = Add-AzureAccount -Credential $Cred
if(!$Account)
{
write-output "Connection to Azure Subscription using the Credential asset failed..."
Break;
}
set-AzureSubscription -SubscriptionName $Subscription
$AzStorageKey = (Get-AzureStorageKey -StorageAccountName $AzStorageName).Primary
$context = New-AzureStorageContext -StorageAccountName $AzStorageName -StorageAccountKey $AzStorageKey
$blobsremoved = 0
$MaxReturn = 10000
$Total = 0
$Token = $Null
$TotalDel = 0
$dateLimit = (get-date).AddDays(-$retentionDays)
try
{
do
{
Write-Output "Retrieving blobs"
$blobs = Get-AzureStorageBlob -Container $container -context $context -MaxCount $MaxReturn -ContinuationToken $Token
$blobstodelete = $blobs | where LastModified -LE $dateLimit
$Total += $Blobs.Count
Write-Output "$Total total Retrieved blobs"
$Token = $Blobs[$blobs.Count -1].ContinuationToken;
if($Blobs.Length -le 0)
{
break;
}
if($blobstodelete.Length -le 0)
{
continue;
}
$TotalDel += $blobstodelete.Count
$blobstodelete | Remove-AzureStorageBlob -Force
Write-Output "$TotalDel blobs deleted"
}
While ($Token -ne $Null)
}
catch
{
write-output $_
}
}
rclone is a great tool to interact with cloud storage.
try rclone purge
As others have already mentioned, you cannot delete a "folder" in Azure Blob Storage. You have to use workaround like listing all files with a prefix and then running a for loop to delete each of them.
In PowerShell, you can simplify these 2 steps in one line by running the following command (using the AzureRM module):
Get-AzureStorageBlob -Context $context -Container $container -Blob 'FolderName*' | Remove-AzureStorageBlob -WhatIf
The -WhatIf option will print out the exact actions it is going to take. What I observed is that it will print What if: Performing the operation "Remove blob" on target ... for each file in the "folder". That probably means this is actually doing individual file deletion.

How to search a string in an Excel using Powershell

I have a folder containing multiple excel files. I want to search for a string like "2501" and find which of my files contains this string then output it's file name to a file (or display it). I wrote some scripts and googled but did not find the answer.
I wrote this :
$Location = "C:\1.xlsx"
$SearchStr = "Mike"
$Sel = Select-String -pattern $SearchStr -path $Location
If ($Sel -eq $null)
{
write-host "$Location does not contain $SearchStr" -ForegroundColor Cyan
}
Else
{
write-host "Found $SearchStr `n$Se in $Location"
}
Write-host "end" -ForegroundColor Yellow
This works only if I specify a txt file, it does not work with Excel.
This may help https://gallery.technet.microsoft.com/office/How-to-search-text-in-e16373b8
Also you may need to loop the folder to search in every excel file

Resources