I've been fooling around with Python for mass file operations for a while now. It's been good so far, especially with how friggin' simple it is to do just about ANY file operation.
At work, I sometimes get requested to run mass site updates. Commonly, I'll be asked to do the same thing to over 30 sites. In these instances, I've found that writing a Python script to handle at least some of that lifting is worthwhile.
In today's example, we're going to cover updating the source files for a bunch of sites. These are dirty hacks, and Windows specific, but they work well enough for me.
First thing I needed to do was copy the latest version of our ASP.NET app to every site. To handle this, I have this:
import os # needed for traversing remote directories
import shutil # needed for file copies and deletes
sn = raw_input( "Folder Name: " ) # ask for the folder name
shutil.rmtree( "\\\\testserver\\inetpub\\webroot" + sn) # completely remove the contents of the directory named for the site
shutil.copytree( "\\\\builds\\asp\\v.1.5", "\\\\testserver\\inetpub\\webroot" + sn) # grab the latest ASPX files for the site
shutil.copytree( "\\\\builds\\bin\\v.1.7", "\\\\testserver\\inetpub\\webroot" + sn + ".wip\\bin" ) # grab the latest DLLs for the site
shutil.copyfile( "C:\\webconfigs\\" + sn + ".config", "\\\\testserver\\inetpub\\webroot" + sn + "\\web.config" ) # copy the web.config for the site and place it
print "Copied!"
"How does this do massive amounts of work? Looks like just one site to me!" Yes, but the Windows console is nifty in a lot of ways. For instance, copy/pasting has some weird quirks and is perfect when you don't want to write or use a parser. Fire it up and go to the directory the script is in:
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.
C:\Documents and Settings\Gh0st_Preacher>f:
F:\>cd f:\scripts
F:\Scripts>dir
Volume in drive F is Gh0stData1
Volume Serial Number is E8F9-F338
Directory of F:\Scripts
01/14/2010 11:59 PM <DIR> .
01/14/2010 11:59 PM <DIR> ..
01/14/2010 11:59 PM 697 copy.py
01/14/2010 11:59 PM 1,954 fileupdate.py
01/14/2010 11:58 PM 268 setro.py
3 File(s) 2,919 bytes
2 Dir(s) 583,399,571,456 bytes free
F:\Scripts>
We're working with "copy.py". Craft a file with a list of the names of the sites you're working with, and put the script before each name, like this :
copy.py
site1
copy.py
site2
copy.py
site3
Stupid, right? Let's see what happens when I copy/paste that into the console window that's currently in F:\scripts:
F:\scripts>copy.py
SN: site1
Copied!
F:\scripts>copy.py
SN: site2
Copied!
F:\scripts>copy.py
SN: site3
Copied!
That's the actual echo. The windows console will wait to paste each line until it has the ability to actually place that text somewhere. Not only that, but it'll translate carriage returns the same as you hitting "enter". Because of this, you don't need to write a file parser for dumb scripts like this. This copy/paste system is stupid - I am wholly aware of this - but it's simple and easy. No extra code. No nothin'. Just things working. I can't really argue with results.
So how else can this be useful? In my case, I have to modify a value in the web.config files I copied. The value will be the same across all sites, since we just need to point the site to a different data machine to grab our head, header, and footer files. here's what I did (credit to TOXiC for the original here):
import fileinput, string, sys # need these for everythang
done = "n"
while done == "n":
sn = raw_input( "sn: " )
fileQuery = "\\\\testserver\\inetpub\\webroot\\" + sn + "\\web.config"
sourceText = "livedata.site.com"
replaceText = "devdata.internal.com"
def replacemachine(fileName, sourceText, replaceText):
file = open(fileName, "r") # open in read-only
text = file.read() # read the file and assign to a variable
file.close() # close out the read session
file = open(fileName, "w") # reopen the file in write mode
file.write(text.replace(sourceText, replaceText)) # do the replace
# and write the new file with the correction.
file.close() # closes the write
print "servicemachine updated"
replacemachine(fileQuery, sourceText, replaceText)
done = raw_input( "done? " )
Now, this time, I decided to get crafty. See that loop in there? You can just keep telling it "n" for "done" and it'll start over again. Starting at F:\scripts, copy/paste a file formatted like this:
fileupdate.py
site1
n
site2
n
site3
Still simple, still stupid, but it still works. Output?
sn: Site1
servicemachine updated
done? n
sn: Site2
servicemachine updated
done? n
sn: Site3
servicemachine updated
done? y
And our updates are done!
We could roll both of these up into a big script, but I'm lazy. Seriously lazy. Copy/paste lazy.
This is an example of duct tape programming. It's dirty, but quick and effective.
Keep it simple, kids.