(四)子命令
前言
在前面的文章中,我们介绍了如何利用 cobra 框架编写命令行程序,以及如何给命令行程序定义选项,已经忘记了的同学可以重温之前的内容:
今天我们的内容是如何实现子命令。
子命令的例子
会 java 的同学,肯定对 mvn 命令不陌生,它是构建 java 程序最常用的工具之一。 mvn 包含多个子命令:
mvn clean
mvn compile
mvn package
这里的 clean
、compile
和 package
都是 mvn
这个命令下的子命令。 子命令可以看作是一种组织命令的方式,将多个相关的子命令组织到一个大的命令下。
再举个例子,npm
命令,通过 npm -h
可以看出该命令下包含 N 多个子命令。
教程目标
我们要实现查指定目录下的指定文件名称开头的文件。例如,查找 /tmp
目录下的前缀是 x
的文件名称。
于是我们实现一个子命令 search
, 同时定义两个命令行选项:-p
用于指定前缀,-d
用于指定目标查找目录(即在该目录下查找)。
./list search -p x -d /tmp
# 或者通过长选项名称方式
./list search --prefix=x --directory=/tmp
实现 search 子命令
为了实现 search 子命令,我们打算分为以下几步:
- 1、利用
cobra-cli
生成 search 子命令,并修改 search 子命令的帮助信息; - 2、定义 search 子命令的命令行选项
-d
和-p
; - 3、获取命令行选项的值,同时实现 search 子命令的业务逻辑。
步骤1 - 生成子命令
进入项目工作目录,使用 cobra-cli
命令添加 search 子命令。
cobra-cli add search
命令执行完毕后,在项目根目录下的 cmd/
目录下 多了一个 search.go,该文件就是我们实现 search 子命令逻辑的地方。
下面就是生成的 search.go 文件中的代码,由于篇幅关系删除了一些注释,并且我们修改了帮助信息:
var searchCmd = &cobra.Command{
Use: "search",
Short: "查找指定目录下指定前缀开头的文件",
Long: `查找指定目录下指定前缀开头的文件。`,
Run: func(cmd *cobra.Command, args []string) {
// 这里实现命令逻辑
},
}
func init() {
rootCmd.AddCommand(searchCmd)
// searchCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
步骤2 - 定义选项
相信看过前面两篇文章的同学,这一步应该是轻车熟路,我们直接给出代码:
func init() {
rootCmd.AddCommand(searchCmd)
searchCmd.Flags().StringP("prefix", "p", "", "待查找的文件名前缀")
searchCmd.Flags().StringP("directory", "d", "", "目标查找目录")
}
步骤3 - 实现子命令逻辑
子命令的逻辑我们打算定义一个函数 searchByPrefix
来实现,在该调用函数之前,我们获取选项的值,并将选项的值作为函数的入参。
prefix, _ := cmd.Flags().GetString("prefix")
dir, _ := cmd.Flags().GetString("directory")
searchByPrefix(dir, prefix)
剩下的就是 searchByPrefix
函数的实现。无非就是利用 strings.HasPrefix
检查文件名称是否以指定前缀开头,这个过于简单,直接指出代码:
func searchByPrefix(dir string, prefix string) {
files, _ := ioutil.ReadDir(dir)
fileNames := make([]string, 0, len(files))
for _, file := range files {
if strings.HasPrefix(file.Name(), prefix) {
fileNames = append(fileNames, file.Name())
}
}
fmt.Println(strings.Join(fileNames, "\n"))
}
完整代码放在 github 上,戳这里查看。或者 clone 整个 list 项目,切换到 easy-command-part4 分支查看。
牛刀小试
让我们来查找下 /tmp
目录下以 s
开头的文件名称。
go run main.go search -d /tmp -p s
#或者先编译出我们的 list 命令行程序
go build
./list search -d /tmp -p s
结语
本篇中,我们介绍了如何利用 cobra-cli
给命令添加子命令,我们以 search 子命令说明了实现方法。值得一提的是,大家可以发挥想象力给 list 添加更多的子命令。
温馨提示:反馈需要登录