3.14 head与tail —— 打印文件的前10行和后10行

当查看上千行的大文件时,我们可不会用cat命令把整个文件内容给打印出来。相反,我们只会查看文件的一小部分内容(例如文件的前10行或后10行)。我们有可能需要打印出文件的前n行或后n行,也有可能需要打印出除了前n行或后n行之外所有的行。

还有一种用例是打印文件的第n行至第m行。

headtail命令可以帮助我们实现这一切。

实战演练

head命令总是读取输入文件的头部。

打印前10行:

  1. $ head file

stdin读取数据:

  1. $ cat text | head

指定打印前几行:

  1. $ head -n 4 file

这个命令会打印文件的前4行。

打印除了最后N行之外所有的行:

  1. $ head -n -N file

注意,-N表示一个负数。

例如,用下面的代码打印除了最后5行之外的所有行:

  1. $ seq 11 | head -n -5
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6

而下面的命令会打印出文件的第1行至第5行:

  1. $ seq 100 | head -n 5

将最后几行排除在打印范围之外是head的非常重要的一个用法。可是总有人去寻找其他复杂的方法来达成这个目的。

打印文件的最后10行:

  1. $ tail file

可以用下面的代码从stdin中读取输入:

  1. $ cat text | tail

打印最后5行:

  1. $ tail -n 5 file

打印除了前N行之外所有的行:

  1. $ tail -n +(N+1)

例如,打印除前5行之外的所有行,N+1=6,因此使用下列命令:

  1. $ seq 100 | tail -n +6

这条命令将打印出第6行至第100行。

tail命令的一个重要用法是从一个内容不断增加的文件中读取数据。新增加的内容总是被添加到文件的尾部,因此当新内容被写入文件的时候,可以用tail将其显示出来。只是简单地使用tail的话,它会读取文件的最后10行,然后退出。然而那时新的内容也许又已经被其他进程追加到文件中了。为了能够不间断地监视文件的增长,tail有一个特殊的选项 -f--follow,它们会使tail密切关注文件中新添加的内容,并随着数据的增加时时保持更新:

  1. $ tail -f growing_file

这种文件内容会不断增加的典型例子就是日志文件。用于监视文件内容增加的命令如下:

  1. # tail -f /var/log/messages

或者

  1. $ dmesg | tail -f

我们不时会运行dmeg 查看内核的环形缓冲区(kernel ring buffer)消息,要么是调试USB设备,要么是查看sdX(X是sd设备的次序列号)。tail -f也可以加入一个睡眠间隔 -s,这样我们就可以设置监视文件更新的时间间隔。

tail具有一个很有意思的特性:当某个给定进程结束之后,tail也会随之终结。

假设我们正在读取一个不断增长的文件,进程Foo一直在向该文件追加数据,那么tail -f就会一直执行,直到进程Foo结束。

  1. $ PID=$(pidof Foo)
  2. $ tail -f file --pid $PID

当进程Foo结束之后,tail也会跟着结束。

让我们实际演练一下。

创建一个新文件file.txt,用gedit打开这个文件(你也可以使用其他文本编辑器)。

向文件添加新内容并不断地将它们保存到gedit中。

现在运行:

  1. $ PID=$(pidof gedit)
  2. $ tail -f file.txt --pid $PID

当你不断对文件进行更新时,更新的内容都会被tail命令写入终端;当关闭gedit时,tail命令也会结束。