Version 8 (modified by mloskot, 6 years ago)

QA: How can I delete feature from Shapefile?

FAQ - Vector

  1. How can I delete feature from Shapefile?
  2. How can I merge hundreds of Shapefiles?
  3. How do I translate a mixed geometry file to shapefile format?
  4. How to quote command parameters for GDAL/OGR utilities in Microsoft …

How can I delete feature from Shapefile?

This question was asked a few times on the mailing list, for instance  here and  here. It's recommended to look at these threads as they provide explanation on how to delete entries from  Shapefile.

It is not possible to delete features from Shapefile using  ogr2ogr utility.

In order to remove entries from Shapefile, you need to call  OGRLayer::DeleteFeature() method, either directly from C++ program or using one of alternative interface like  OGR C API or bindings to other programming languages.

How can I merge hundreds of Shapefiles?

Here's a bash script to bulk load a directory of shapefiles that have the same schema to postgis. It could obviously be made smarter, but it seems to do the trick.

#!/bin/bash

# let OGR create a table from one of the files
ogr2ogr -f Postgresql PG:"host=smoke.hobu.net" -a_srs "EPSG:26915" -nln outputlayer first_input_shape.shp -overwrite -nlt POLYGON

# delete all the data in the table we just created (but don't delete the table)
ogrinfo PG:"host=smoke.hobu.net" -sql "delete  from outputlayer"

# loop through all of the shapefiles in the directory and load them
for i in $(ls *.shp); do
  ogr2ogr -f Postgresql PG:"host=smoke.hobu.net" -a_srs " EPSG:26915" -nln outputlayer $i -update -append -skipfailures
done 

*Note if you get an import error from postgis similiar to "ERROR: new row for relation "layer1" violates check constraint" you should try substituting "-nlt GEOMETRY" for your GEOMETRY TYPE (in the above example it is POLYGON). This will avoid errors if your shapefile includes both Polygon and Multipolygon geometries, for example. See this thread  http://postgis.refractions.net/pipermail/postgis-users/2006-June/012495.html

These Unix shell steps illustrate how to batch merge multiple shapefiles into a single shapefile using OGR. This assumes you have downloaded a group of shapefiles in .zip format which are all the same type of data but just need to be combined. This works on a Mac but has not been test on other versions of UNIX:

#Make a new directory called "tmp" and a sub directory called "merged"
mkdir tmp
mkdir tmp/merged

#copy all zipped files to the "tmp" directory and then "cd" into it
cp *.zip tmp
cd tmp

#unzip all the .zip archives
find . -name "*.zip" -exec unzip '{}' \;

#delete all .zip archives
rm *.zip

#move a single shapefile (and the cooresponded .shx, .dbf, etc files) to the "merged" directory (exchange 'myshape*' for the name of one of your shapefiles keeping the '*' at the end of the name)
find . -name 'myshape*' -exec mv '{}' merged \;
 
#Batch merge all the remaining shapefiles from the tmp dir into the copied file in the merge dir (exchange 'myshape' for the name of the copied shapefile)
for i in $(ls *.shp); do ogr2ogr -f 'ESRI Shapefile' -update -append merged $i -nln myshape
done

This Windows cmd shell example merges multiple *wetlands*shapefiles in the current directory to a single merged\wetlands.shp (double % to put in a script, %f --> %%f):

mkdir merged
for %f in (*wetland*.shp) do (
  if not exist merged\wetlands.shp (
      ogr2ogr -f "esri shapefile" merged\wetlands.shp %f) else (
      ogr2ogr -f "esri shapefile" -update -append merged\wetlands.shp %f -nln Wetlands )
)

The trick is to use the first input to create a new shapefile, and thereafter only update and append. See the end of  http://www.gdal.org/ogr/drv_shapefile.html

If you don't need to specify a human friendly name via -nln, using -append by itself is simpler:

 for %f in (dir1\*.shp dir2\*.shp) do (ogr2ogr -f "esri shapefile" -append merged %f)

How do I translate a mixed geometry file to shapefile format?

Some formats (such as ESRI Shapefiles) only allow one type of geometry in a layer, while other formats (such as DGN, MapInfo?, GML) allow a mixture of geometry types within a single layer. Direct attempts to translate result in errors like this:

% ogr2ogr out.shp mixed.dgn 
ERROR 1: Attempt to write non-linestring (POLYGON) geometry to ARC type shapefile.
ERROR 1: Terminating translation prematurely after failed
translation of layer elements

The first step in dealing with such a problem is to discover what geometry types exist in the source file. For a DGN file called mixed.dgn, with a layer called elements this can be accomplished using the following OGR SQL command (see  OGR SQL tutorial for details):

% ogrinfo -ro mixed.dgn -sql 'select distinct ogr_geometry from elements'
INFO: Open of `mixed.dgn'
      using driver `DGN' successful.

Layer name: elements
Geometry: Unknown (any)
Feature Count: 1
Layer SRS WKT:
(unknown)
ogr_geometry: String (0.0)
OGRFeature(elements):0
  ogr_geometry (String) = LINESTRING

OGRFeature(elements):1
  ogr_geometry (String) = POLYGON

OGRFeature(elements):2
  ogr_geometry (String) = POINT

This file has point, line and polygon geometries. Each will need to be translated to a separate output file.

% ogr2ogr out_point.shp mixed.dgn -where 'ogr_geometry = "POINT"'
% ogr2ogr out_line.shp mixed.dgn -where 'ogr_geometry = "LINESTRING"'
% ogr2ogr out_poly.shp mixed.dgn -where 'ogr_geometry = "POLYGON"'

How to quote command parameters for GDAL/OGR utilities in Microsoft Windows CLI

When working with Windows  CLI, it's helpful to remember that quoting rules are different to those used on Unix. Here is example of properly quoted SQL statement passed to  ogrinfo (or  ogr2ogr) with -sql option:

ogrinfo . -sql "SELECT * FROM 'B_Major Cities 1' WHERE FID = 49"

The whole SQL statement is wrapped with double quotes, but not single quotes. The name of table (here it works against ESRI Shapefile in current directory, note the dot) includes spaces, so it must be wrapped with single quotes.

For contrast, these two variants present incorrect command:

ogrinfo . -sql 'SELECT * FROM 'B_Major Cities 1' WHERE FID = 49'
ogrinfo . -sql 'SELECT * FROM "B_Major Cities 1" WHERE FID = 49'