Here is a quick code block that I use quite often to copy directories from a management server to a ton of other servers.
Copy-Item [-Recurse]
For the pros or even a beginner, you’re done, you’ve got the command you wanted… but did you think about the rest of the information in this blog? Keep reading!
The problem is a request comes across your desk, more often than we want to admit, saying “We” need to update this file or files on these completely random machines. Then you given a list of servers and you need to quickly copy files to them.
Solutions
- Save the list of servers to a text file, read it in with Get-Content. This works cumbersome when in RDP and PS Remitting Environments
- Reformat them into a PowerShell array by putting quotes around each of them and commas. Example:
$Computers = @( "Server01", "Server02", "Server03.mydomain.local", "Server06" )
- Using/modifying the code at the bottom of this blog post
$content = Get-Content C:\Temp\SomeRandomFileCopy176.txt
Myself, I love scripts, I love modules, but what I love more than anything is the flexibility of PowerShell. I even love copying and pasting blocks or one liners directly into PowerShell. So for the copy task presented above here is the magic that my mind goes through:
- Which machines do I need to copy files to
- Are all the machines online
- Test that the destination share path is reachable on all machines
- Fix any errors with the remote destinations or simply remove them from the list
- Copy the files
Here-Strings to the Rescue
Normally when you create a string in PowerShell, or an array it has some form of structure it has to follow. With a Here-String,
$MyHereString = @" This can be some random te text that and it's formatting will be preserved when the Here-String variable is used" "@ $MyHereString
This can be some random te text that and it's formatting will be preserved when the Here-String variable is used"
So instead of creating some random temp file on the management server every time, I simply open my Microsoft OneNote and copy and paste the code below. But the technique I use to manage the list of machines is called a PowerShell “Here-String”. Then further down in the code will “convert” the Here-String into an array so that we can easily loop through it. In my opinion when using reusable code blocks, PowerShell Here-Strings are the most forgiving and easiest/fastest to work with as they maintain formatting. To use a Here-String, the unformatted text, in this case a list of machines, are encapsulated between a starting @” tag and a close “@.
*Note* The closing “@ MUST BE on its own line and in column 1.
Again, this is code I copy and paste directly into a PS Window. It allows flexibility when logging into a locked down Remote Desktop environment or when using PowerShell remoting.
Here is the sample script to copy a directory from a source server to the servers listed in the $Computers Here-String below.
$Computers = @" Server01 Server02 Server03.mydomain.local Server06 Server07 Server08 Server09 Server26 Server27 Server28 Server29 Server30.mydomain.local Server35 Server36 Server45 Server46 Server112 Server113 Server114 "@ # Here we will set the source and remote share location and path $SourceDir = "D:\Software\Datadog\v5.8.5-x64-privatefix" $RemoteSharePath = "D$\Software\Datadog" # Loop through the Here-String, trim each line and build the ComputersArray $ComputersArray = @() $Computers.Split("`n") | % { if ($_.Trim()) { $ComputersArray += $_.Trim() } } $AllRemoteSharePathsExist = $True # Do a precheck to see if all the remote directories are reachable and exist $ComputersArray | % { If ((Test-Path "\\$_\$RemoteSharePath") -eq $False) { Write-Host -ForegroundColor Red "[PreCheck Error] \\$_\$RemoteSharePath does not exist" $AllRemoteSharePathsExist = $False } } # If the precheck passes, then copy and overwrite existing files If ($AllRemoteSharePathsExist) { $ComputersArray | % { Write-Host "[$_] Copying $SourceDir to \\$_\$RemoteSharePath"; Copy-Item -Path "$SourceDir" -Destination "\\$_\$RemoteSharePath" -Recurse -Force } } Else { Write-Host "Errors Exist, Exiting" }
Happy Copying!
If one of the destination computers path doesn’t exist it prevents it from copying to any of them. What’s a method to get around this