> For the complete documentation index, see [llms.txt](https://man.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://man.bsdcn.org/man1/ctags.1.md).

# ctags(1)

`ctags` — 创建 tags 文件

## 名称

`ctags`

## 概要

`ctags [-BFTaduwvx] [-f tagsfile] file`

## 描述

`ctags` 实用程序根据指定的 C、Pascal、Fortran、yacc(1)、lex(1) 和 Lisp 源文件，为 ex(1) 生成 `tags` 文件。tags 文件给出一组文件中指定对象的位置。tags 文件的每一行包含对象名称、定义该对象的文件，以及用于对象定义的搜索模式，三者以空白分隔。通过使用 `tags` 文件，ex(1) 可以快速定位这些对象定义。根据提供给 `ctags` 的选项，对象将包括子程序、typedef、define、struct、enum 和 union。

以下选项可用：

**`-B`** 使用反向搜索模式（`?...?`）。

**`-F`** 使用正向搜索模式（`/.../`）（默认）。

**`-T`** 不为 typedef、struct、union 和 enum 创建标签。

**`-a`** 追加到 `tags` 文件。

**`-d`** 为不带参数的 `#defines` 创建标签；带参数的 `#defines` 会自动添加标签。

**`-f`** 将标签描述放入名为 `tagsfile` 的文件中。默认行为是将它们放入名为 `tags` 的文件中。如果 `tagsfile` 为 “-”，则标签将写入标准输出。

**`-u`** 更新 `tags` 文件中指定的文件，即删除对它们的所有引用，并将新值追加到文件中。如果 tags 文件不存在或不是常规文件（例如使用了 `-f`- 写入标准输出），则忽略此选项。注意：此选项的实现方式相当慢；通常直接重建 `tags` 文件更快。

**`-w`** 抑制警告诊断信息。

**`-x`** `ctags` 生成对象名称列表、每个对象定义所在的行号和文件名，以及该行的文本，并打印到标准输出。这是一个简单的索引，可作为可离线阅读的函数索引打印出来。

名称以 `.c` 或 `.h` 结尾的文件被假定为 C 源文件，并搜索 C 风格的例程和宏定义。名称以 `.y` 结尾的文件被假定为 yacc(1) 源文件。名称以 `.l` 结尾的文件，如果其第一个非空白字符为 `;`、`(` 或 `[`，则被假定为 Lisp 文件，否则被视为 lex(1) 文件。其他文件首先检查是否包含 Pascal 或 Fortran 例程定义，如果没有，则搜索 C 风格的定义。

在 C 程序中，标签 “`main`” 会被特殊处理。生成的标签通过在文件名前加 `M` 来创建，并去除尾部的 `.c` 和任何前导路径名组件。这使得在包含多个程序的目录中使用 `ctags` 变得实用。

yacc(1) 和 lex(1) 文件各有特殊标签。“`yyparse`” 是 yacc(1) 文件第二部分的开始，“`yylex`” 是 lex(1) 文件第二部分的开始。

## 文件

**`tags`** 默认输出 tags 文件

## 退出状态

`ctags` 实用程序发生错误时退出值为 1，否则为 0。重复的对象不被视为错误。

## 兼容性

`-t` 选项是一个空操作，用于与之前默认不为 typedef、enum、struct 和 union 创建标签的 `ctags` 版本兼容。

## 参见

ex(1), [vi(1)](/man1/vi.1.md)

## 标准

`ctags` 实用程序遵循 IEEE Std 1003.1-2001 ("POSIX.1")。

## 历史

`ctags` 实用程序出现于 3.0BSD。

## 缺陷

对 Fortran 和 Pascal 的函数、子程序和过程的识别方式非常简单。没有尝试处理块结构；如果在不同块中有两个同名的 Pascal 过程，将会丢失信息。`ctags` 实用程序不理解 Pascal 类型。

决定搜索 C、Pascal 还是 Fortran 函数的方法只是一种权宜之计。

`ctags` 实用程序依赖输入格式正确，任何语法错误都会使其完全混淆。它也会对某些合法语法感到困惑；例如，由于它不理解 `#ifdef`（顺便说一句，这是一个功能而非缺陷），`#ifdef` 内部任何大括号不平衡的代码都会使其有些迷失方向。类似地，定义内的多行更改会导致它将对象的最后一行而非第一行作为搜索模式。多行 `typedef` 的最后一行也会被类似地记录。
