- GIS
- 遥感
- 数据工程
【免费下载链接】gdal
GDAL is an open source MIT licensed translator library for raster and vector geospatial data formats.
GDAL 3.13 新增的gdal vector rename-layer子命令用于批量重命名矢量数据集的图层:既可以把单个图层改成一个指定名字,也可以通过 ASCII 化、转小写、文件名兼容化、替换保留字符、截断长度等一系列变换规则批量清洗图层名,并自动处理重名冲突。本文以 gdal_vector_rename_layer.rst 为主干,结合 gdalalg_vector_rename_layer.cpp 源码实现与 test_gdalalg_vector_rename_layer.py 测试用例,完整讲解两种工作模式、全部选项语义、底层执行原理及可复现的实战示例,让你读完即可在 GPKG、ESRI Shapefile 等格式间正确完成图层重命名任务。
命令概览与两种工作模式
gdal vector rename-layer属于 GDAL 3.13 新增的矢量子命令(见 gdal_vector_rename_layer.rst#L9),它同时是gdal vector pipeline流水线中的一步,可被其它步骤串联使用。命令的核心用途正如 gdalalg_vector_rename_layer.h 中定义的描述:Rename layer(s) of a vector dataset.(重命名矢量数据集的图层)。
命令提供两种模式:
- 指定名称模式:用
--output-layer把(一个)图层改名为给定名称;当数据集中存在多个图层时,必须同时配合--input-layer指明要改名的那个图层。 - 批量清洗模式:不指定具体目标名,而是通过一组变换规则强制修改图层名:
--ascii:把字符强制转为 ASCII;--lower-case:强制转为小写;--filename-compatible:强制与文件名兼容(跨 Linux / Windows / macOS 通用规则);--reserved-characters:从给定保留字符列表中移除或替换字符;--max-length:截断到最大字符数。
在批量清洗模式下,除按规则改写名字外,命令还会自动尝试保证图层名唯一:对重名图层追加_{N}后缀(N 为序号)。需要注意,若--max-length设置得过小,唯一性可能无法达成(源码与文档均明确提示此限制,见 gdal_vector_rename_layer.rst#L48-L50)。
两个例子即可直观理解两种模式(同样来自文档的 Examples 节,见 gdal_vector_rename_layer.rst#L139-L152):
# 模式一:把指定图层改名为用户选择的名字 $ gdal vector rename-layer input.gpkg output.gpkg --input-layer "name with space" --output-layer "without_space" # 模式二:批量强制 ASCII、小写、去空格、文件名兼容 $ gdal vector rename-layer input.gpkg output_shp_directory --output-format "ESRI Shapefile" --ascii --lower-case --filename-compatible --reserved-characters " "程序特定选项详解
本节逐项说明 rename-layer 特有的 9 个选项,语义均来自 gdal_vector_rename_layer.rst#L57-L98,并结合源码中的参数注册与校验逻辑展开。
--input-layer <INPUT-LAYER>
输入图层的名字,必须与--output-layer一起使用。源码在 gdalalg_vector_rename_layer.cpp#L38 通过AddLayerNameArg(&m_inputLayerName)注册该参数,并在校验阶段(L59-L95)强制执行两条规则:
- 指定了
--input-layer但未指定--output-layer时,直接报错:Argument output-layer must be specified when input-layer is specified; - 指定了
--input-layer但输入数据集中不存在该图层时,报错:Input layer 'xxx' does not exist。
这两条错误路径也都有对应测试用例覆盖(test_gdalalg_vector_rename_layer.py#L38-L65)。
--output-layer <OUTPUT-LAYER>
输出图层的名字。若输入有多个图层,则必须同时指定--output-layer(即配合--input-layer指出要对哪个图层改名)。反向校验同样存在:只给了--output-layer而输入数据集图层数 ≥ 2 且未给--input-layer时,报错Argument input-layer must be specified when output-layer is specified and there is more than one layer,测试见 test_gdalalg_vector_rename_layer.py#L67-L79。
在流水线(pipeline)场景下,--output-layer通过AddOutputLayerNameArg()注册(gdalalg_vector_rename_layer.cpp#L39-L43),并允许在 pipeline 步骤中设置输出图层名(SetOutputLayerNameAvailableInPipelineStep(true))。
--ascii
强制把字符转为 ASCII。目前只有Latin-1 Supplement与Latin Extended-A字符集中的重音字符具备合理的 ASCII 等价替换;其它非 ASCII 字符将被移除,或者被--replacement-character指定的替换字符取代。
其底层实现是 CPLUTF8ForceToASCII():该函数内部维护一张拉丁字符映射表,例如À(0xC0)→A、Æ(0xC6)→AE、Ñ(0xD1)→N等,无法映射的字符则替换为传入的chReplacementChar。在 rename-layer 中调用时(gdalalg_vector_rename_layer.cpp#L338-L344),替换字符取自--replacement-character。
测试用例印证了行为:test_gdalalg_vector_rename_layer.py#L82-L107 中,图层名év😊en加--ascii后变成even(é→e,表情符号被移除);加--replacement-character "?"后则变成ev?en(无法 ASCII 化的字符被替换)。
--lower-case
强制转为小写。目前只对 ASCII 大写字符(A–Z)生效。若同时指定了--ascii,--lower-case在--ascii之后应用。源码中就是简单的逐字节范围转换(gdalalg_vector_rename_layer.cpp#L345-L352),测试见 test_gdalalg_vector_rename_layer.py#L141-L153:UPPERCASE→uppercase。
--filename-compatible
强制图层名与 Linux、Windows 或 macOS 的文件名兼容——重点是不依赖命令实际运行的操作系统,即在任意平台上都套用最严格的跨平台规则。其底层实现是 CPLLaunderForFilenameSafe(),规则包括:
- 保留字符
<、>、:、"、/、\、|、?、*、^(FAT 文件系统非法)及 ASCII 控制字符(< 32 与 127)被替换为替换字符,或(替换字符为 NUL 时)直接移除; - 保留名(如
CON、PRN、AUX、NUL、COM1–COM9、LPT1–LPT9、CONIN$、CONOUT$,不区分大小写)会被追加替换字符/下划线; - 以空格或点结尾的名字会被追加替换字符/下划线(这同时规避了 POSIX 上非法的
.与..)。
测试用例中的CON经过--filename-compatible后变成CON_,正是上述保留名处理规则的直接验证(test_gdalalg_vector_rename_layer.py#L110-L123)。
--reserved-characters <RESERVED-CHARACTERS>
需要移除或替换的保留字符列表(可一次给出多个字符,如" "表示空格)。被列出的字符将替换为--replacement-character指定的字符(若给出),否则直接移除。源码实现是逐字符扫描并与保留字符串比对(gdalalg_vector_rename_layer.cpp#L316-L332)。测试with space+--reserved-characters " "+--replacement-character "_"得到with_space(test_gdalalg_vector_rename_layer.py#L125-L139)。
--replacement-character <REPLACEMENT-CHARACTER>
ASCII 转换不可能时的替换字符,或用来替换保留字符。该选项在注册时被限制为最多 1 个字符(SetMaxCharCount(1),见 gdalalg_vector_rename_layer.cpp#L52-L55)。注意:若该字符本身是非 ASCII 字符,则它在传给底层CPLUTF8ForceToASCII/CPLLaunderForFilenameSafe时会被取字节使用,实际场景建议使用 ASCII 字符。
--max-length <MAX-LENGTH>
截断到最大字符数。注册时限定最小值为 1(SetMinValueIncluded(1),见 gdalalg_vector_rename_layer.cpp#L56-L57)。值得强调的是,截断按UTF-8 字符计数而非字节:源码中的 TruncateUTF8ToMaxChar() 会跳过 UTF-8 多字节序列的后续字节,绝不会把一个多字节字符拦腰截断,因此éven限长 3 得到éve(不是被截坏的字节串),noël得到noë,测试见 test_gdalalg_vector_rename_layer.py#L156-L168。
处理顺序与唯一性保证机制
批量清洗模式下,各变换按固定顺序应用(见 RunStep() 第一遍扫描):
--reserved-characters处理保留字符(替换或移除);--filename-compatible做文件名兼容化(传入替换字符);--ascii做 ASCII 化;--lower-case转小写;--max-length截断。
之后对处理结果计数,若存在重名(bNonUniqueNames),则进入第二遍处理:按出现顺序对每个重名名字追加_{N}后缀。后缀的宽度随同名数量自适应:≤ 9 个时用_1、_2…,10–99 个时用_01、_02…,更多时用三位(见 gdalalg_vector_rename_layer.cpp#L364-L406)。
当--max-length参与时,后缀会被“挤”进长度限制:名字先按max-length 减去后缀长度截断再拼上后缀。测试 test_gdalalg_vector_rename_layer.py#L184-L200 中,sâme_name与abéc各出现两次、限长 5,最终得到sâm_1、sâm_2、abé_1、abé_2。但如果--max-length小到连后缀都放不下(后缀本身超过限长),命令只能放弃唯一性:发出警告Cannot create unique name for 'xxx' while respecting N maximum length,并输出仍重名的图层(test_gdalalg_vector_rename_layer.py#L202-L216 中same_name限长 2 得到两个sa)。
此外,若某个图层经变换后名字未变化,则该图层走直通(passthrough)路径,不创建额外的包装层(gdalalg_vector_rename_layer.cpp#L413-L430),减少不必要的开销。
底层实现原理:包装图层与关系表同步
rename-layer 并非把数据复制一遍再改名,而是构建一层“视图”式输出。从源码结构看,它的实现基于两个内部类:
- GDALVectorRenameLayerAlgorithmLayer(gdalalg_vector_rename_layer.cpp#L105-L191):继承
GDALVectorPipelineOutputLayer,克隆源图层定义(OGRFeatureDefn)后通过SetName()设置新名字,特征对象在TranslateFeature()中仅被替换为新的图层定义(SetFDefnUnsafe)后原样透传,字段、几何、FID 均不改变;GetFeatureCount、GetExtent、空间/属性过滤器等都委托给源图层。 - GDALVectorRenameLayerAlgorithmDataset(gdalalg_vector_rename_layer.cpp#L197-L261):继承
GDALVectorPipelineOutputDataset,维护“旧图层名 → 新图层名”的映射,并重写GetRelationship():当数据集的图层关系(relationship)涉及被改名的图层时,自动把关系中的LeftTableName、RightTableName、MappingTableName同步为新名。
关系同步这一点在测试中有详细验证(test_gdalalg_vector_rename_layer.py#L218-L303):例如把关系left_right_media中的left图层改名为renamed后,关系仍被保留,且GetLeftTableName()变为renamed、GetRightTableName()仍为right、GetMappingTableName()仍为left_right。这意味着包含关联表(如 GPKG 的关系扩展)的数据集在改名后关系不会断裂。
在gdal vector pipeline中作为流水线步骤使用
gdal vector rename-layer同时也是矢量流水线的一个可用步骤(文档 gdal_vector_rename_layer.rst#L52 与 gdal_vector_pipeline.rst#L231-L236 均有说明)。在 pipeline 场景下,rename-layer 的步骤描述即rename-layer,可通过gdal vector pipeline --help-doc=rename-layer查看其详细选项。
测试用例展示了典型用法(test_gdalalg_vector_rename_layer.py#L306-L316):
gdal vector pipeline input.gpkg --pipeline "read ! rename-layer --input-layer=test --output-layer=renamed"该用法基于源码中的GDALVectorRenameLayerAlgorithm类(gdalalg_vector_rename_layer.h):它继承GDALVectorPipelineStepAlgorithm,以standaloneStep标志区分独立命令与流水线步骤两种形态——作为流水线步骤时通过AddOutputLayerNameArg()显式暴露--output-layer参数(gdalalg_vector_rename_layer.cpp#L39-L43)。类注册与构建位于 gdalalg_vector.cpp 与 apps/CMakeLists.txt。
标准选项
除程序特定选项外,该命令还接受一组与其它gdal vector系列子命令一致的标准选项(文档通过 include 引用,见 gdal_vector_rename_layer.rst#L100-L129):
| 选项 | 说明 |
|---|---|
--append | 允许向已有图层追加要素;若输出数据集尚不存在则同时创建(见 append_vector.rst) |
--co <NAME>=<VALUE> | 数据集创建选项,可重复,具体可用项依输出格式而定(见 co_vector.rst) |
--if <format> | 尝试用于打开输入文件的格式/驱动名,可重复,用于跳过自动驱动探测(见 if.rst) |
--lco <NAME>=<VALUE> | 图层创建选项,可重复,具体可用项依输出格式而定(见 lco.rst) |
--oo <NAME>=<VALUE> | 输入数据集打开选项(格式相关),可重复(见 oo.rst) |
-f, --of, --format, --output-format <OUTPUT-FORMAT> | 输出矢量格式,可用值可通过gdal --formats | grep vector | grep rw | sort列出(见 of_vector.rst) |
--output-layer <NAME> | 输出图层名;未指定时输出图层名与输入图层名一致(见 output_layer.rst) |
--output-open-option, --output-oo <NAME>=<VALUE> | 输出数据集打开选项(格式相关),可重复,GDAL 3.12 起可用(见 output_oo.rst) |
--overwrite | 允许覆盖已存在的目标文件/数据集;默认若目标已存在则报错(见 overwrite.rst) |
--overwrite-layer | 允许覆盖已存在的输出矢量图层(见 overwrite_layer.rst) |
--skip-errors | 是否忽略写入要素失败(GDAL 3.12 起)。注意:该选项会把事务单元设为一次一个要素,在写入数据库时可能显著变慢(见 skip_errors.rst) |
--update | 是否以更新模式打开已存在的输出数据集(见 update.rst) |
--upsert | --append的变体(GDAL 3.12 起),使用UpsertFeature而非CreateFeature插入或更新要素,目前仅少数驱动实现(GPKG、ElasticSearch、MongoDBv3)(见 upsert.rst) |
实战示例
以下示例可直接复现。测试数据可用 GDAL 自带测试数据(如 autotest/ogr/data/poly.shp,其在 test_ogrsf 集成测试中也被用于 rename-layer 验证,见 test_gdalalg_vector_rename_layer.py#L319-L334),或自建 GPKG。
示例 1:把含空格的图层名改为无空格名(指定名称模式)
$ gdal vector rename-layer input.gpkg output.gpkg --input-layer "name with space" --output-layer "without_space"示例 2:为输出到 Shapefile 目录批量清洗图层名(批量清洗模式)
$ gdal vector rename-layer input.gpkg output_shp_directory --output-format "ESRI Shapefile" --ascii --lower-case --filename-compatible --reserved-characters " "该命令把所有图层名先转 ASCII(如École→Ecole),再转小写,再去除空格、保证与跨平台文件名兼容,最后自动解决重名。
示例 3:保留字符替换与长度截断
# 空格替换为下划线,并限制最长 20 个字符 $ gdal vector rename-layer input.gpkg output.gpkg --reserved-characters " " --replacement-character "_" --max-length 20示例 4:在流水线中串联使用
$ gdal vector pipeline input.gpkg --pipeline "read ! rename-layer --input-layer=test --output-layer=renamed"参数组合建议:
--replacement-character配合--ascii或--reserved-characters使用才有意义,单独使用不会生效;--max-length会按 UTF-8 字符计数,中文等多字节字符不会被截坏,可放心用于含非拉丁字符的图层名;- 当
--max-length与大量重名图层叠加时,若限长过小,命令会发出Cannot create unique name ...警告且不保证唯一性,请为后缀预留足够空间; - 输出到 GPKG、Shapefile 等格式时,如需覆盖已存在文件请加
--overwrite。
小结
gdal vector rename-layer用一条命令解决了“图层重命名”这个矢量数据准备中的高频需求:既支持单个图层的精确改名,也支持跨平台一致的批量清洗(ASCII、小写、文件名兼容、保留字符、截断),还自动处理重名唯一性,并能在流水线中与其它矢量步骤无缝衔接。其底层通过包装层(而非数据复制)实现,字段、几何与要素内容原样保留,同时智能同步图层关系表。配合源码实现(gdalalg_vector_rename_layer.cpp)、底层工具函数(cpl_path.cpp、cpl_recode.cpp)与完整测试(test_gdalalg_vector_rename_layer.py),读者可深入理解每个选项的确切行为,并在自己的数据管线中放心使用。
- GIS
- 遥感
- 数据工程
【免费下载链接】gdal
GDAL is an open source MIT licensed translator library for raster and vector geospatial data formats.
相关推荐
GDAL `--input-layer` 图层筛选选项完全指南:矢量管线、子命令用法与 `--active-layer` 协同
GDAL input layer 图层筛选选项完全指南:矢量管线、子命令用法与 active layer 协同 导读 input layer <INPUT LA
GIS遥感数据工程GDAL `gdal dataset rename` 命令详解:安全重命名数据集及其伴生文件
GDAL gdal dataset rename 命令详解:安全重命名数据集及其伴生文件 gdal dataset rename 是 GDAL 3.12 引入的
GIS遥感数据工程GDAL `--append` 矢量图层追加详解:从命令行到源码实现
GDAL append 矢量图层追加详解:从命令行到源码实现 导读 本文聚焦 GDAL 新版命令行体系(3.11 起引入的 gdal vector 系列子命令)
GIS遥感数据工程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考