Robert Ward
Robert Ward

Reputation: 11

PowerShell script to perform 2 different commands on data from a 2 column csv file

With PowerShell I am trying to take information from a CSV file and execute two commands that are based on two columns of data. The first piece of data is an asset that needs to copy a unique file to a folder and have renamed to config.txt.

The second piece of data is a name for a computer to have the folder that had received the unique file copied to the named computer. For example;

First command:

Copy-Item "c:\folder1\$asset.txt" -Destination "f:\folder2\config.txt"

Second command:

robocopy /e folder2 \\$ComputerName\folder3

The data is imported from a csv file that has two columns, asset and computername. The script is at follows and is one of many variations, none of which has worked including the one below. Any help would be much appreciated.

Computers.csv contains the following

A12345  CN12345
A54321  CN54321

Script:

Import-Csv -Delimiter ',' -Path c:\temp\computers.csv -Header 'Asset','ComputerName’ | 
   ForEach-Object {
     $asset += $_.asset
     $ComputerName += $_.NBN
     Copy-Item "c:\folder1\$asset.txt" -Destination "f:\folder2\config.txt"
     robocopy /e  f:\folder2 \\$ComputerName\folder3 
   }

I have worked on the script and the results are below. The script does what I want except I manually have to change the position of the items in the array. I would like to have this done automatically but haven't figured that part out yet. I expect the csv file to contain 50 or more assets and computer names and don't look forward entering in the positions of each item and running the script 50 times. Is there a way to go through the array automatically?

$computers = Import-Csv -Path c:\temp\computers.csv -Header 'Asset','ComputerName' $asset = $computers[0].asset $ComputerName = $computers[0].ComputerName

ForEach-Object {

  Copy-Item "c:\folder1\$asset.txt" -Destination "f:\folder2\config.txt"
 
  robocopy /e /is "f:\folder2\" "\\$ComputerName\c$\folder3"  
  }

Upvotes: 1

Views: 127

Answers (1)

emanresu
emanresu

Reputation: 974

First, make sure that your csv does not already contain headers. If it does, and you use the -header flag then a duplicate header will be added to the contents.

I tested this solution using a csv, with no header, with these contents:

abc,123,
def,456,
ghi,789

Whenever I'm debugging code that involves accessing values in a loop, I like to write some code to write those values to the console like this:

$assetIndex = 0
Import-Csv -Header Asset,ComputerName -Path C:\noHeader.csv | 
ForEach-Object {
    Write-Host ([string]::Concat('Asset at index ',$assetIndex, ': The asset value is "', $_.Asset, '", The computer name is "', $_.ComputerName,'"'))
    $assetIndex++
}

Running that will prove that we are correctly accessing values inside the loop. Lastly, string concatenation can be a little confusing inside loops when accessing values with $_.

Here are 2 examples of how you could build your copy-item file path inside the loop:

#example 1
"c:\folder1\$($_.asset).txt"
#example 2
[string]::Concat('c:\folder1\',$_.Asset, '.txt')

Putting it all together we get:

Import-Csv -Header Asset,ComputerName -Path C:\noHeader.csv | 
ForEach-Object {
  Copy-Item "c:\folder1\$($_.asset).txt" -Destination "f:\folder2\config.txt"
  robocopy /e /is "f:\folder2\" "\\$($_.ComputerName)\c$\folder3" 
}

When placing variables inside of quotes, if you want to access the properties of that variable then you need to use the $($myVariable.someProperty) syntax, otherwise the .someProperty will just be interpreted as a string.

Upvotes: 1

Related Questions