Here is how I accomplished this problem by using a Python script to daisy-chain several ogr2ogr instructions together. You could easily convert it to a batch script, basically I just concatenate together ogr2ogr instructions (cmd
), then execute them by calling os.system(cmd)
, passing-in the ogr2ogr command I concatenated together.
The secret weapon is (as @capooti demonstrated) applying OGR_SQL to impose the filename as a constant value of the source dataset you are appending into your merge result.
In my example, the -sql
flag handles this, in the code it's like this:
-sql "SELECT \'' + filename + '\' AS filename, * FROM ' + filenameNoExt + '"'
But that's confusing to read because I need to apply single quotes and double quotes in the resulting concatenation. To do that I have to escape the single quotes (i.e. ') to use them "for real". So for readability, it helps to see it without variables and escape sequences. If you pretend the filename was "roads1" for a particular iteration, the resulting concatenation would look like this in the ogr2ogr sentence:
-sql "SELECT 'roads1.shp' AS filename, * FROM roads1"
This .py script is an amalgamation of three tricks I stole from matt wilkie (an empty, clone of a shapefile), j03lar50n (adding a column to a shapefile using ogrinfo and ogr_sql), and capooti (using ogr_sql to impose a fixed column value on all records in a shapefile). So here's the full script:
# merge_shps.py
import os
path = "D:/GIS/01_tutorials/ND_Roads/extracted" # path to your folder of .shp files
merge = "merge_filename" # this will be the name of your merged result
directory = os.listdir(path)
count = 0
for filename in directory:
if ".SHP" in filename.upper() and not ".XML" in filename.upper():
# On the first pass, create a clone and add the filename column.
if count == 0:
# Make a clone (matt wilkie)..
cmd = 'ogr2ogr ' + path + '/' + merge + '.shp ' + path + '/' + filename + ' -where "FID < 0"'
os.system(cmd)
# Add the field (j03lar50n)..
cmd = 'ogrinfo ' + path + '/' + merge + '.shp -sql "ALTER TABLE ' + merge + ' ADD COLUMN filename character(50)"'
os.system(cmd)
# Now populate the data (capooti)..
print "Merging: " + str(filename)
# You'll need the filename without the .shp extension for the OGR_SQL..
filenameNoExt = filename.replace(".shp","")
cmd = 'ogr2ogr -f "esri shapefile" -update -append ' + \
path + '/' + merge + '.shp ' + \
path + '/' + filename + \
' -sql "SELECT \'' + filename + '\' AS filename, * FROM ' + filenameNoExt + '"'
# Uncomment this line to spit the ogr2ogr sentence to the terminal..
#print "\n" + cmd + "\n"
os.system(cmd)
count += 1