How Can I Copy the Same File to a Number of Different Computers?

How Can I Copy the Same File to a Number of Different Computers?

  • Comments 18
  • Likes
Hey, Scripting Guy! Question

Hey, Scripting Guy! I regularly update a file that needs to be copied to all of my servers. How can I write a script that will copy the same file (to the same folder) on multiple computers?

-- JU

SpacerHey, Scripting Guy! AnswerScript Center

Hey, JU. It’s Monday, May 14th as we write this column, which mean that Mother’s Day in the US is over. And that’s good. Not that the Scripting Guys have anything against mothers, mind you. It’s just that we agree with Anna Jarvis, the person largely responsible for getting Mother’s Day proclaimed a holiday in the first place. After devoting years of her life to the cause, Jarvis soon came to regret having done so; she actually spent the final years of her life trying to get rid of Mother’s Day. Why? Because she was extremely disappointed that a day set aside to honor mothers quickly became just another reason to sell flowers and greeting cards. She was totally aghast that, in just a few years, her simple little holiday had gone commercial.

As a general rule the Scripting Guys are all for commercialization. (In fact, if anyone from Pepsi is reading this, don’t you think The Pepsi-Cola Bottling Company Presents Hey, Scripting Guy! has a nice ring to it?) However, the combination of Mother’s Day and commercialization can only mean one thing: the Scripting Dad and the Scripting Son have to go out shopping. Together.

The Scripting Dad and the Scripting Son get along incredibly well, and they do a lot of things together. Truth be told, the Scripting Dad has always believed that if they ever had a contest for Father and Son Who Get Along the Best he and the Scripting Son would be a shoe-in … unless, of course, the contest was held at a shopping mall. At that point, all bets would be off.

To give you a hint of what we’re talking about, the two had no sooner walked into the mall when the Scripting Son found the … perfect … present. “Mom has an MP3 player,” he said. “Let’s get her a case for that and then go.”

“Well, we can get her the case,” said the wise and thoughtful Scripting Dad. “But that’s not enough; we’ll have to get her something else as well.”

“Stop yelling at me! Every time we go shopping you end up yelling at me.”

Which, come to think of it, might very well be true.

Believe it or not, the two eventually found a present, bought it, and made it back home safe and sound (a little bruised and battered, but both still alive). Interestingly enough, in addition to buying a present for his mom, the Scripting Son somehow managed to get two new T-shirts and a couple scoops of Double Chocolate frozen yogurt for himself out of the trip as well.

Thank goodness he isn’t spoiled.

Oh, well. The moral of the story? If the Scripting Dad and the Scripting Son can survive a trip to the mall together, copying the same file to multiple computers ought to be a piece of cake:

Const ForReading = 1
Const OverwriteExisting = TRUE

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\Scripts\Computers.txt")

Do Until objFile.AtEndOfStream
    strComputer = objFile.ReadLine
    strRemoteFile = "\\" & strComputer & "\C$\Scripts\Test.doc"
    objFSO.CopyFile "C:\Scripts\Test.doc", strRemoteFile, OverwriteExisting
Loop

Before we go much further we should point out that there are a number of different ways we could approach the issue of copying files to multiple computers. We chose to tackle this task by reading computer names from a text file. (This is known as the Peter Costantini Memorial Approach in honor of the legendary Peter Costantini, who never met a script he couldn’t enhance by having it read computer names from a text file.) Would you rather select computer names from a dialog box, supply computer names as command-line arguments, or maybe grab the names of all the computers in an OU? Then you need to take a look at our Remote/Multiple Computer Scripting Templates, don’t you?

We’re assuming that we have a very simple little text file (C:\Scripts\Computers.txt) containing the names of all the computers we need to copy the file to. That text file should look something like this:

atl-fs-01
atl-fs-02
atl-fs-03
atl-fs-04
atl-fs-05

Note. In case you’re wondering, this is known as the Bob Wells Memorial Text File, in honor of the legendary Bob Wells, who developed the official Scripting Guys computer naming convention back in 1768. Bob hailed from the legendary – and mythical – city of Atlanta, which is why our computer names always start with the letters atl.

Like we said, in case you’ve been wondering.

As you might expect, our plan is to open the text file, read in the computer names, and then copy the file to each of those machines.

To do that we start out by defining a pair of constants, ForReading and OverWriteExisting. We’ll need the ForReading constant to open the text file for reading; we’ll need the OverWriteExisting constant in order to copy over any existing version of the target file that might already be lingering on one of the remote computers.

Note. Yes, there are a lot of nuances involved in copying files, aren’t there? That’s one good reason why you should read this month’s Sesame Script column.

What do you mean you need two good reasons before you’ll read the column? Fine; this month you’ll also learn what the word subrogation means.

With the constants defined we next create an instance of the Scripting.FileSystemObject object, then use the OpenTextFile method to open the file C:\Scripts\Computers.txt (the file containing our list of computer names):

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\Scripts\Computers.txt")

With the text file open our next step is to read through the file line-by-line. To do that we set up a Do Until loop designed to run until we’ve reached the end of the file (or, if you prefer, until the file’s AtEndOfStream property is True):

Do Until objFile.AtEndOfStream

The first thing we do inside that loop? We use the ReadLine method to read the initial line of the file (that is, the first computer name) and then store that value in a variable named strComputer:

strComputer = objFile.ReadLine

Now it gets a tiny bit tricky. If you’re a devoted reader of Hey, Scripting Guy! (and you don’t have to answer that; like Santa Claus, we know who’s been bad or good) then you know that we always mention the fact that the FileSystemObject is designed to work against the local computer. And that’s true; that’s exactly what it’s designed for. However, the FileSystemObject can work with UNC paths. That means that we can copy a file to a shared folder on a remote computer (for example, \\atl-fs-01\Public\Shared_Files). It also means that we can copy a file to any folder on a remote computer provided that we use the administrative share (e.g., \\atl-fs-01\C$\Scripts). In our example, we’re going to use the administrative share.

Note. Does that mean that this script will fail if you’ve disconnected the administrative share on a computer? Yes. For better or worse you’ll have to use either an administrative share or a shared folder in order to perform this task.

In a minute or two we’ll use the CopyFile method to copy the file to the first computer listed in Computers.txt. Before we can do that, however, we need two pieces of information: the complete path to the file we want to copy, and the complete path (including file name) to the location where we want the file copied. Determining the path to the file to be copied is easy; after all, that’s a file stored on our local computer. (In this case, C:\Scripts\Test.doc).

Determining the location on the remote computer is a bit more complciated; that’s because we need to use UNC paths, and one key element of the UNC path – the computer name – will change with each iteration of our loop. Shoot; it is hopeless, isn’t it?

Oh, wait: no it’s not. After all, that’s what this line of code is for:

strRemoteFile = "\\" & strComputer & "\C$\Scripts\Test.doc"

All we’re doing here is constructing a UNC path, substituting the value of the variable strComputer for the computer name. When we’re done combining the various parts of the path we’ll end up with a value like this, which we then assign to the variable strRemoteFile:

\\atl-fs-01\C$\Scripts\Test.doc

And guess what? That value just happens to be the UNC path we need in order to copy the file to the computer atl-fs-01. That’s something we do using this line of code:

objFSO.CopyFile "C:\Scripts\Test.doc", strRemoteFile, OverwriteExisting

Here, at long last, we call the CopyFile method, passing three parameters:

The path to the local file (C:\Scripts\Test.doc), the file we want copied.

The UNC path for the remote computer (stashed in the variable strRemoteFile).

The constant OverWriteExisting (just in case Test.doc already exists in the C:\Scripts folder on atl-fs-01).

We copy the file, then loop around and repeat the process with the next computer in the list.

And that, as they say in the movie business, is a wrap.

That should get you started, JU. And don’t worry: we wouldn’t let you go without one last Mother’s Day anecdote. When the Scripting Son was a few months old his Scripting Mom went back to work, and the Scripting Son started going to a day care in downtown Seattle. For Mother’s Day the babies all “made” their mothers little ceramic handprints engraved with their names and the date. (Yes, very cute.) When the Scripting Dad went to pick up the Scripting Son the Friday before Father’s Day he assumed he’d get a similar gift. Instead, he got absolutely nothing. He jokingly mentioned this to one of the day care providers, who replied – in all seriousness – “We don’t do anything for Father’s Day. Most children don’t have fathers.”

Obviously the Scripting Dad should have paid more attention in his high school biology class.

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • First off nice script. Second how can I make this script write to a text file for each computer in the text file with a success or failure. I tried several things none of which worked. And when I tested it with a computer that was offline the entire script failed. Any help on this would be appreciated.

  • Hi

    Whenever I try to run this script, I get the following error:

    Missing statement body in do loop.

    At D:\PowerShell\CopyDSRStoreDay.ps1:7 char:4

    + Do U <<<< ntil objFile.AtEndOfStream

    Any ideas why this is happening?

    Thanks

    Mike

  • Does exactly what I need.......only it doesn't work :(

    Receiving the exact error that Mike is getting.

  • @ Mike & Matt

    This is not Powershell, this is VBScript...

    You just have to save this script with a vbs extension and it will work.

  • how to copy a set of files to multiple machine

  • is this how we need to do

    Const ForReading = 1

    Const OverwriteExisting = TRUE

    Set objFSO = CreateObject("Scripting.FileSystemObject")

    Set objfile = objFSO.OpenTextFile("C:\Documents and Settings\cshadmin\Desktop\New Folder\copy.text")

    Do Until objFile.AtEndOfStream

       strComputer = objFile.ReadLine

       strRemoteFile = "\\" & strComputer & "\c$\"

       objFSO.GetFolder "C:\Documents and Settings\cshadmin\Desktop\script\cmd", strRemoteFile, OverwriteExisting

    Loop

  • Is there a way to export the results to a log file?

  • This script is great but what can be done to find if there was a break or get the list of computers that it could not be delivered?

  • @Scott you will need to check for errors or success, and if you have a success, then add line to log to a file, or event log. You will add the code inside the Do ... Loop portion.

    @Sudhir Negi  you will need to check for errors, and if an error occurs, then write to your log file. You can pick up the name of the computer that failed from the StrComputer variable.

  • nice useful script. but it fails when a computer in the list is not reachable with error "path not found" for the target folder. Any idea as to how we can skip those machines which are not reachable? Thanks a ton.

  • @somesh

    You can add the on error line, see below. This will allow the script to keep going.

    Const ForReading = 1

    Const OverwriteExisting = TRUE

    on error resume next

    Set objFSO = CreateObject("Scripting.FileSystemObject")

    Set objFile = objFSO.OpenTextFile("C:\Computers.txt")

  • @mawyer, @somesh

    Bad solution.  Use WIn32_PingStatus to test the computer before tryng to access the resource.

    Post you questions to the Hey Scripting Guy's forum: social.technet.microsoft.com/.../ITCG

  • I try to use this script with a text file which resume informations about script execution, but it doesn't work. Furthermore, i have to check the path on each server, because it can be on C or D.Can you help me check this?

    This is my code:

    "Option Explicit

    Dim objFSO,Myfile

    Const ForReading = 1, ForWriting = 2, ForAppending = 8

    Set RepD ="\D$\tools\delage32.exe"

    Set RepC ="\C$\tools\delage32.exe"

    set WshShell = CreateObject("WScript.Shell")

    Set WshNetwork = WScript.CreateObject("WScript.Network")

    Set Path = RepC or RepD

    Set objFSO=CreateObject("Scripting.FileSystemObject")

    Const OverwriteExisting = TRUE

    'creation du fichier bilan

    if objFSO.FileExists("\\filsar01\COMMUNS\Bilan_remplacement_delage32.txt")=false then

    Set MyFile= objFSO.OpenTextFile("\\filsar01\COMMUNS\Bilan_remplacement_delage32.txt", ForAppending, True)

    End If

    'definition de la liste de serveurs

    Set objFile = objFSO.OpenTextFile("\\filsar01\COMMUNS\liste_srv.txt")

    'boucle de copie

    Do Until objFile.AtEndOfStream

       strComputer = objFile.ReadLine

    For Each strComputer in objFile

    If RepD=true Then

    Set Path = RepD

    Else

    Set Path = RepC

    End If

       strRemoteFile = "\\" & strComputer & Path

    objFSO.CopyFile Path, strRemoteFile, OverwriteExisting

    'On remplit le fichier bilan

    MyFile.WriteLine ( "& strComputer &" : remplacement terminé dans )"Path" )

    Loop

    'on ferme le fichier texte

    MyFile.Close"

  • Script worked! Now let's say I want to delete the files I've copied. What would this looks like in a separate script?

    Thanks

  • Const ForReading = 1

    Const OverwriteExisting = TRUE

    Set objFSO = CreateObject("Scripting.FileSystemObject")

    Set objFile = objFSO.OpenTextFile("C:\Scripts\Computers.txt")

    Do Until objFile.AtEndOfStream

        strComputer = objFile.ReadLine

        strRemoteFile = "\\" & strComputer & "C$\Scripts\Test.doc"

        objFSO.DeleteFile strRemoteFile

    Loop