golang cli
With the capability to build lightweight yet efficient system, Golang has been getting a lot of attention from software engineers who use it to build backend services, microservices etc as well as DevOps engineers who use it as scripting language. FYI, Kubernetes is written in Go as well.
具有构建轻便高效系统的功能,Golang受到了使用它构建后端服务,微服务等的软件工程师以及将其用作脚本语言的DevOps工程师的广泛关注。 仅供参考,Kubernetes也是用Go编写的。
In this article, we will be looking at how to build a CLI-based tool to rename files in batch using spf13/cobra. While there are other libraries that can be used to build CLI application, Cobra offers the usage of flags, arguments validation, auto-generated help command, suggestion when there is typo and many more.
在本文中,我们将研究如何构建基于CLI的工具,以使用spf13 / cobra批量重命名文件。 虽然还有其他库可用于构建CLI应用程序,但Cobra会提供标志的用法,参数验证,自动生成的帮助命令,出现错别字时的建议等。
Let’s get start on building our file renaming tool. Before diving into the code, let’s lay out the requirements:
让我们开始构建文件重命名工具。 在深入研究代码之前,让我们对需求进行布局:
- Ability to specify the target folder 能够指定目标文件夹
- Ability to scan all files in subfolders能够扫描子文件夹中的所有文件
- Ability to include or exclude files based on name or extension能够根据名称或扩展名包含或排除文件
根命令(Root command)
First, we start by defining a root command which will be called in the main.go
. Also, we can create a folder called cmd
where we can store all the command files.
首先,我们先定义一个root命令,该命令将在main.go
。 另外,我们可以创建一个名为cmd
的文件夹,在其中可以存储所有命令文件。
To execute the root command from main.go, we can add the following line in the main()
function:
要从main.go执行root命令,我们可以在main()
函数中添加以下行:
cmd.RootCmd.Execute()
With just a few lines, we can already see the CLI application in action. Simply run go run main.go
and we will see auto-generated help message on the root command similar to the picture below:
仅需几行,我们已经可以看到运行中的CLI应用程序。 只需运行go run main.go
,我们将在root命令上看到自动生成的帮助消息,如下图所示:
子指令(Sub command)
Next, we can add more commands to the root command. For example, in the code below, we are adding sub command rename
so we can execute commands as such filezy rename
.
接下来,我们可以在root命令中添加更多命令。 例如,在下面的代码中,我们添加了子命令rename
因此我们可以执行诸如filezy rename
这样的命令。
Cobra comes with built in validators that check on the arguments on the command. In the code excerpt above, cobra.ExactArgs(1)
ensures that there is only 1 positional argument and throws error if validation fails. One (1) number of argument is exactly what we need where we allow users to key in the new file name.
Cobra附带有内置的验证器,它们可以检查命令中的参数。 在上面的代码摘录中, cobra.ExactArgs(1)
确保只有1个位置参数,并且如果验证失败,则会引发错误。 一(1)个参数正是我们需要的,我们允许用户键入新文件名。
renameCmd.Flags().StringVarP(&folder, "folder", "f", "./", "Target folder to be scanned")
Cobra also provides simple way to add flags. In the example above, we are adding a flag -f
to the renameCmd
with default value as ./
. To specify a different folder like /c/folder
, we can trigger the command as such: filezy rename [filename] -f /c/folder
.
眼镜蛇还提供了添加标记的简单方法。 在上面的示例中,我们将标志-f
添加到renameCmd
,默认值为./
。 要指定其他文件夹(如/c/folder
,我们可以这样触发命令: filezy rename [filename] -f /c/folder
。
从文件夹读取文件 (Read files from folder)
After specifying a flag to read the folder input, let’s implement the logic to read files from the folder.
在指定一个标志以读取文件夹输入后,让我们实现从文件夹中读取文件的逻辑。
Read files from a folder 从文件夹读取文件First, it opens the folder in os.Open(folder)
then the Readdir(-1)
function returns all the FileInfo from the folder in slice. We then loop through all the FileInfo in the slice and append it to files
array if it is a folder. The file name will be used later for renaming purposes.
首先,它在os.Open(folder)
打开文件夹,然后Readdir(-1)
函数从slice中的文件夹返回所有FileInfo。 然后,我们遍历切片中的所有FileInfo并将其附加到files
数组(如果它是文件夹)。 该文件名将在以后用于重命名。
从子文件夹递归读取文件 (Read files from subfolder recursively)
While the above codes can read the files in the current folder and we can possibly call the function to read the directory again when it hits the subfolder, it involves a lot of codes and this can be solved using path/filepath
standard library.
尽管上面的代码可以读取当前文件夹中的文件,并且我们可以调用该函数以在子文件夹中再次读取目录,但是它涉及很多代码,可以使用path/filepath
标准库来解决。
The walk function walks the file tree starting from the folder given (as root) into each file or directory in the tree. Note that it can be quite slow when it comes to a large directory.
巡视功能将文件树从给定的文件夹(作为根目录)开始移入树中的每个文件或目录。 请注意,对于大型目录,它可能会非常慢。
添加过滤器 (Adding filter)
Not all of the files scanned shall be renamed and that’s why it’s advisable to add a filter to include or exclude files based on the file name or extension. There are several filters that I can think of, for example based on prefix, suffix, regex pattern and extension.
并非所有扫描的文件都应重命名,因此,建议根据文件名或扩展名添加过滤器以包括或排除文件。 我可以想到几种过滤器,例如基于前缀,后缀,正则表达式模式和扩展名的过滤器。
To ease the process, it will be easier that we can store the file name in separate fields such as base file name and extension. Again, with the use of flags, we can get the input of prefix, suffix, regex or extension.
为了简化此过程,将文件名存储在单独的字段(例如基本文件名和扩展名)中会更加容易。 同样,使用标志,我们可以获得前缀,后缀,正则表达式或扩展名的输入。
Filter files based on file name 根据文件名过滤文件strings
and regexp
are the two standard library that provides string comparison on prefix and suffix and string matching based on regex pattern.
strings
和正则regexp
是两个标准库,提供了前缀和后缀的字符串比较以及基于正则表达式模式的字符串匹配。
文件编号 (Numbering of the files)
As we are renaming the files in batch where they can potentially be overwritten, we should come up with a mechanism to add an auto-increment number as suffix to the file name.
当我们批量重命名文件时,它们有可能被覆盖,因此,我们应该想出一种机制,在文件名中添加一个自动递增的数字作为后缀。
Besides that, we should keep the sequence of the files the same as before. To achieve this, simply appending number will mess up the sequence of the files. To give you an example, assuming that there are 20 files to be renamed and the names will be as such: file-1.jpg, file-2.jpg, … … file-10.jpg, file-11.jpg… … file-20.jpg. As a result, file-10.jpg will be sorted before file-2.jpg.
除此之外,我们应该保持文件顺序与以前相同。 为了达到这个目的,只需加上数字就会弄乱文件的顺序。 举一个例子,假设有20个文件被重命名,名称将是这样:file-1.jpg,file-2.jpg,………file-10.jpg,file-11.jpg…………文件20.jpg。 结果,file-10.jpg将在file-2.jpg之前排序。
To avoid the sequence being reordered, we can add zero in front of the numbers to standardize the number of digits of the suffix. In the code excerpt below, we create two helper functions: to calculate the number of digits of the total number of files and to get the auto-incremental suffix number.
为避免对序列进行重新排序,我们可以在数字前面添加零以标准化后缀的位数。 在下面的代码摘录中,我们创建两个帮助器函数:计算文件总数的位数并获取自动递增的后缀数。
Getting the auto-incremental suffix 获取自动递增的后缀重命名文件(Renaming the files)
With the old file name and newly built file name, we can call the following function to rename the files.
使用旧文件名和新建文件名,我们可以调用以下函数来重命名文件。
os.Rename(, )
Do note that if there is existing file name that coincides with the new file name, then the existing file will be replaced.
请注意,如果现有文件名与新文件名一致,则将替换现有文件。
构建并运行 (Build and run)
We have come to an end and we can build the Go application by running go build
. We can then add the folder where the built application is to the PATH so that we can run it from the command prompt.
我们已经结束了,我们可以通过运行go build
来构建Go应用程序。 然后,我们可以将构建的应用程序所在的文件夹添加到PATH,以便我们可以在命令提示符下运行它。
Source code: https://github.com/wilsontwm/filezy
源代码: https : //github.com/wilsontwm/filezy
Thanks and cheers!
谢谢和欢呼!
翻译自: https://medium.com/swlh/building-cli-based-file-renaming-tool-with-golang-e3c6a16eedf6
golang cli