文件

自带的文件管理系统是 IDE 亮点功能之一,从最基本的文件移动、重命名和删除功能,到更加具体的编译和句法检查。批量文件的操作也非常有用,比如找出某种后缀或大小的所有文件,或者搜索出有一定命名模式的文件。在本系列的第一篇文章里,我将考察一些非常有用的工具来对批量文件进行操作,这些工具应该也是大多数 Linux 用户所熟知的。

列举文件

ls 恐怕是某管理员最初学的用以显示某路径下的文件列表的命令之一,而大多数管理员也应该是知道 -a-l 选项,它们分别是用来显示包括点文件(即隐藏文件)在内的所有文件和更详细的文件相关的信息栏。

还有一些 ls 的选项不那么常用,但是对编程很有帮助:

  • -t —— 按最后编辑日期排序,最新的最先。这在某个大目录里找出最近修改的文件列表时很有用,比如将结果导入( pipehead 或者 sed 10q。或许加上 -l 会效果更好。当然如果你想获取最旧的文件列表,只要加 -r 反转列表即可。
  • -X —— 按文件类型分类。这在多语言或多后缀的项目中特别方便,比如头文件和源文件分开,或区分开源文件和生成文件或目录。
  • -v —— 按照文件名里的版本号排序。
  • -S —— 按文件大小排序。
  • -R —— 递归地列举文件。这个选项和 -l 组合使用并将结果导出到 less 效果很好。

因为生成的列表就是文本,所以你其实可以把结果导出给类似 vim 的进程,然后再加上一些对每个文件作用的解释,这就成了一个目录文件,又或者把列表加进 README 文件:

$ ls -XR | vim -

这种工作其实我们可以很容易地让 make 自动生成,我会在之后的文章里谈到。

查找文件

非常有趣的是你其实可以只用一个 find 命令,不用任何其他参数就列出所有文件,甚至还包括相对路径。当然如果把结果导入 sort 肯定效果更好:

$ find | sort
.
./Makefile
./README
./build
./client.c
./client.h
./common.h
./project.c
./server.c
./server.h
./tests
./tests/suite1.pl
./tests/suite2.pl
./tests/suite3.pl
./tests/suite4.pl

如果你想要 ls -l 样式的列表,只要在 find 后面加上 -ls

$ find -ls | sort -k 11
1155096    4 drwxr-xr-x   4 tom      tom          4096 Feb 10 09:37 .
1155152    4 drwxr-xr-x   2 tom      tom          4096 Feb 10 09:17 ./build
1155155    4 -rw-r--r--   1 tom      tom          2290 Jan 11 07:21 ./client.c
1155157    4 -rw-r--r--   1 tom      tom          1871 Jan 11 16:41 ./client.h
1155159   32 -rw-r--r--   1 tom      tom         30390 Jan 10 15:29 ./common.h
1155153   24 -rw-r--r--   1 tom      tom         21170 Jan 11 05:43 ./Makefile
1155154   16 -rw-r--r--   1 tom      tom         13966 Jan 14 07:39 ./project.c
1155080   28 -rw-r--r--   1 tom      tom         25840 Jan 15 22:28 ./README
1155156   32 -rw-r--r--   1 tom      tom         31124 Jan 11 02:34 ./server.c
1155158    4 -rw-r--r--   1 tom      tom          3599 Jan 16 05:27 ./server.h
1155160    4 drwxr-xr-x   2 tom      tom          4096 Feb 10 09:29 ./tests
1155161    4 -rw-r--r--   1 tom      tom           288 Jan 13 03:04 ./tests/suite1.pl
1155162    4 -rw-r--r--   1 tom      tom          1792 Jan 13 10:06 ./tests/suite2.pl
1155163    4 -rw-r--r--   1 tom      tom           112 Jan  9 23:42 ./tests/suite3.pl
1155164    4 -rw-r--r--   1 tom      tom           144 Jan 15 02:10 ./tests/suite4.pl

要注意,在这种情况下,我得设定 sort 对第11列排序,即对文件名排序;这里所用的标签是 -k

find 有它自己的一套复杂的过滤语句。下面列举的是一些最常用的你可以用以获取某些文件列表的过滤器:

  • find -name '*.c' —— 查找符合某 shell 式样式的文件名的文件。用 iname 开启大小写不敏感搜索。
  • find -path '*test*' —— 查找符合某 shell 式样式的路径的文件。用 ipath 开启大小写不敏感搜索。
  • find -mtime -5 —— 查找近五天内编辑过的文件。你也可以用 +5 来查找五天之前编辑过的文件。
  • find -newer server.c —— 查找比 server.c 更新的文件。
  • file -type d —— 查找所有文件夹。如果想找出所有文件,那就用 -type f;找符号连接就用 -type l

要注意,上面提到的这些过滤器都是可以组合使用的,例如找出近两天内编辑过的 C 源码:

$ find -name '*.c' -mtime -2

默认情况下, find 对搜索结果所采取的动作只是简单地通过标准输出输出一个列表,然而其实还有其他一些有用的后续动作:

  • -ls —— 如前文,提供了一种类 ls -l 式的列表。

  • -delete —— 删除符合查找条件的文件。

  • -exec —— 对搜索结果里的每个文件都运行某个命令, {} 会被替换成适当的文件名,并且命令用 \; 终结。例如:

    $ find -name '*.pl' -exec perl -c {} \;
    

    你也可以使用 + 作为终止符来对所有结果运行一次命令。我还发现一个我经常使用的小技巧,就是用 find 生成一个文件列表,然后在 Vim 的垂直分窗中编辑:

    $ find -name '*.c' -exec vim {} +
    

早先版本的 Unix as IDE 建议 xargs find 配合使用。在大多数情况下并不需要这么做,而且使用 -exec 或是 while read -r 循环的方式来处理文件名中带空格的文件更加灵活。

搜索文件

更多时候,我们对基于文件内容的搜索比基于文件属性的搜索更感兴趣。这毫无疑问用 grep,更加具体来说,应该是 grep -R。它会递归地找出当前目录下符合‘someVar’的文件:

$ grep -FR 'someVar' .

別忘了大小不敏感的标签,因为 grep 默认工作方式是大小写敏感的:

$ grep -iR 'somevar' .

而且,你也可以用 grep -l 光打印出符合条件的文件名而非文件内容选段。

$ grep -lR 'somevar' .

如果你写的脚本或批处理任务需要上面的输出内容,可以使用 whileread 来处理文件名中的空格和其他特殊字符:

grep -lR someVar | while IFS= read -r file; do
    head "$file"
done

如果你在你的项目里使用了版本控制软件,它通常会在 .svn.git.hg 目录下包含一些元数据。你也可以很容易地用 grep -v 把这些目录移出搜索范围,当然得用 grep -F 指定一个恰当且确定的字符串,即要移除的目录名:

$ grep -R 'someVar' . | grep -vF '.svn'

部分版本的 grep 包含了 --exclude--exclude-dir 选项,这看起来更加易读。

当然,还有另外一种很流行的 代替 grep 的工具叫做 ack,默认情况下它就帮你把上面那些个麻烦的东西免除了。它同样也支持大多数黑客最爱的 Perl 兼容的正则表达式(PCRE)。而且它还有很多实用功能来帮助你完成有关源代码的工作。当然使用古朴的 grep 没什么不好的,无论怎样它是 Unix 系统自带的,但是如果你可以安装 ack,我还是非常推荐的。现在你已经可以很容易地用个叫 ack-grep Debian 包或者一个 Perl 脚本来安装。

我提到用一些较新的 Perl 脚本来代替经典工具 grep 可能会让一些 Unix 纯粹主义者很不爽。但是我不认为 Unix 哲学或以 Unix 作 IDE ,就是非要在有一些可用来解决新问题的工具时反而使用一些“古典”工具,毕竟这些新工具跟那些“古典”工具在思想上是一致的。

文件元数据

file 工具可以对所给的文件一行简短的介绍,它用文件后缀、头部信息和一些其他的线索来判断文件。你在检查一堆你不熟悉的文件时使用 find 非常方便:

$ find -exec file {} \;
.:            directory
./hanoi:      Perl script, ASCII text executable
./.hanoi.swp: Vim swap file, version 7.3
./factorial:  Perl script, ASCII text executable
./bits.c:     C source, ASCII text
./bits:       ELF 32-bit LSB executable, Intel 80386, version ...

匹配文件

作为本篇文章的最后一个技巧,我会建议你学习一些有关模式匹配和 Bash 下的括号表达式。你可以在我之前的一篇叫做 Bash shell expansion 的文章里看到。

以上便把经典 Unix 命令行变成了一个可在编程项目中使用的非常强大的文件管理器。