Script to Copy File in Modelbuilder

5136
11
Jump to solution
04-08-2016 03:07 PM
ChrisHolmes
Occasional Contributor III

Hi all,

I have a very simple python script to copy a file from one location to another:

import shutil

shutil.copy("c:/chris/Test1/CitizenComments.mxd" , "c:/chris/test2/CitizenComments.mxd")

If I take this script and put it in a model builder model, what change would I have to make to the code so that I could have a parameter in the model where a user could enter an index string to be appended to the front of the file name?

Thanks!

Chrs

0 Kudos
1 Solution

Accepted Solutions
curtvprice
MVP Esteemed Contributor

I suggest reading the help about how to set up input and output parameters to scripts.​ Once that is set up, you can right-click your script tool to expose its parameters in the model. The script needs to handle input and output parameters like this:

import arcpy
string = arcpy.GetParameterAsText(0)
import shutil
shutil.copy("c:/chris/Test1/CitizenComments.mxd",
            "c:/chris/test2/{}CitizenComments.mxd".format(string))
arcpy.SetParameterAsText(1,  "c:/chris/test2/{}CitizenComments.mxd".format(string)))

Then, set your script tool with an input parameter of type String and a derived parameter of type File. Then re-add your tool to ModelBuilder and I think you'll get what you're looking for.

Or, you can avoid having to set up a separate script tool by using the very useful Calculate Value model-only tool -- a little Python goes a long way in ModelBuilder! You can get this tool added to your model with a right click.

Expression:

CopyFile(r"%String%")

Code Block

import shutil
def CopyFile(string):
  shutil.copy("c:/chris/Test1/CitizenComments.mxd",
              "c:/chris/test2/{}CitizenComments.mxd".format(string))
  return "c:/chris/test2/{}CitizenComments.mxd".format(string)

Data Type

File

Set your parameter String as type String and use the magic wand tool to make it a precondition to Calculate Value, and you're good to go!'

ChrisTool_tbx("Trump") will copy your map document to the path

C:\chris\test2\TrumpCitizenComments.mxd

View solution in original post

11 Replies
ChrisHolmes
Occasional Contributor III

Oh ya, as you can tell: new to python

0 Kudos
curtvprice
MVP Esteemed Contributor

I suggest reading the help about how to set up input and output parameters to scripts.​ Once that is set up, you can right-click your script tool to expose its parameters in the model. The script needs to handle input and output parameters like this:

import arcpy
string = arcpy.GetParameterAsText(0)
import shutil
shutil.copy("c:/chris/Test1/CitizenComments.mxd",
            "c:/chris/test2/{}CitizenComments.mxd".format(string))
arcpy.SetParameterAsText(1,  "c:/chris/test2/{}CitizenComments.mxd".format(string)))

Then, set your script tool with an input parameter of type String and a derived parameter of type File. Then re-add your tool to ModelBuilder and I think you'll get what you're looking for.

Or, you can avoid having to set up a separate script tool by using the very useful Calculate Value model-only tool -- a little Python goes a long way in ModelBuilder! You can get this tool added to your model with a right click.

Expression:

CopyFile(r"%String%")

Code Block

import shutil
def CopyFile(string):
  shutil.copy("c:/chris/Test1/CitizenComments.mxd",
              "c:/chris/test2/{}CitizenComments.mxd".format(string))
  return "c:/chris/test2/{}CitizenComments.mxd".format(string)

Data Type

File

Set your parameter String as type String and use the magic wand tool to make it a precondition to Calculate Value, and you're good to go!'

ChrisTool_tbx("Trump") will copy your map document to the path

C:\chris\test2\TrumpCitizenComments.mxd

ChrisHolmes
Occasional Contributor III

Thanks Curtis, I'll check this out.

Chris

0 Kudos
ChrisHolmes
Occasional Contributor III

Thanks Curtis, following your advice I was able to get the copy file working using:

If I wanted to modify the code block to first create a folder with the same name as what is appended to the copied CitizenComments.mxd file what would need to be changed? So for example the new file path would be C:\chris\105\105CitizenComments.mxd

I had tried the following based on the previous copy file code, but obviously I'm missing some stuff:

import os
import shutil
def CopyFile(string):
   os.mkdir("c:/chris/{}.format(string))
   shutil.copy("c:/chris/Test1/CitizenComments.mxd",
                     "c:/chris/{}/{}CitizenComments.mxd".format(string))
   return "c:/chris/{}/{}CitizenComments.mxd".format(string)
curtvprice
MVP Esteemed Contributor

This is how you use a value twice in a format string. The way to debug this kind of thing is to find a Python prompt (the one in ArcMap will do) and type stuff at it:

>>> "{} {}".format("foo")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: tuple index out of range
>>> "{} {}".format("foo", "foo")
'foo foo'
>>> "{} {}".format("foo", "bar")
'foo bar'
>>> "{0} {0}".format("foo")
'foo foo'

import os
import shutil
def CopyFile(string):
   os.mkdir("c:/chris/{}.format(string))
   shutil.copy("c:/chris/Test1/CitizenComments.mxd",
                     "c:/chris/{0}/{0}CitizenComments.mxd".format(string))
   return "c:/chris/{0}/{0}CitizenComments.mxd".format(string)

7.1. string — Common string operations — Python 2.7.11 documentation

This is really helpful guide to Python string formatting I have bookmarked:

mkaz.tech – Python String Format Cookbook

ChrisHolmes
Occasional Contributor III

Thanks again for the help Curtis, this is super. Also thanks for the link!

0 Kudos
ChrisHolmes
Occasional Contributor III

So I have the above code working to copy multiple files, but it doesn't work to copy a file geodatabase. Any suggestions for how to do this?

Thanks very much for all the help,

Chris

0 Kudos
curtvprice
MVP Esteemed Contributor

either shutil.copytree() or arcpy.Copy_management() should work.

ChrisHolmes
Occasional Contributor III

Thanks Curtis!

I first tried arcpy.Copy_management() and was able to get it working but my efforts to get it to use the parameter so the destination could change based on the user input failed.

So then I tried shutil.copytree() and it looks like it works:

shutil.copytree("x:/GIS/LUAM/DEV/TEMPLATE/data_for_item.gdb","c:/chris/{0}/data_for_item.gdb".format(string))

Have a good weekend.