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