3.14 head与tail —— 打印文件的前10行和后10行
当查看上千行的大文件时,我们可不会用cat
命令把整个文件内容给打印出来。相反,我们只会查看文件的一小部分内容(例如文件的前10行或后10行)。我们有可能需要打印出文件的前n行或后n行,也有可能需要打印出除了前n行或后n行之外所有的行。
还有一种用例是打印文件的第n行至第m行。
head
和tail
命令可以帮助我们实现这一切。
实战演练
head
命令总是读取输入文件的头部。
打印前10行:
- $ head file
从stdin
读取数据:
- $ cat text | head
指定打印前几行:
- $ head -n 4 file
这个命令会打印文件的前4行。
打印除了最后N行之外所有的行:
- $ head -n -N file
注意,-N
表示一个负数。
例如,用下面的代码打印除了最后5行之外的所有行:
- $ seq 11 | head -n -5
- 1
- 2
- 3
- 4
- 5
- 6
而下面的命令会打印出文件的第1行至第5行:
- $ seq 100 | head -n 5
将最后几行排除在打印范围之外是head
的非常重要的一个用法。可是总有人去寻找其他复杂的方法来达成这个目的。
打印文件的最后10行:
- $ tail file
可以用下面的代码从stdin
中读取输入:
- $ cat text | tail
打印最后5行:
- $ tail -n 5 file
打印除了前N行之外所有的行:
- $ tail -n +(N+1)
例如,打印除前5行之外的所有行,N+1=6
,因此使用下列命令:
- $ seq 100 | tail -n +6
这条命令将打印出第6行至第100行。
tail
命令的一个重要用法是从一个内容不断增加的文件中读取数据。新增加的内容总是被添加到文件的尾部,因此当新内容被写入文件的时候,可以用tail
将其显示出来。只是简单地使用tail
的话,它会读取文件的最后10行,然后退出。然而那时新的内容也许又已经被其他进程追加到文件中了。为了能够不间断地监视文件的增长,tail
有一个特殊的选项 -f
或 --follow
,它们会使tail
密切关注文件中新添加的内容,并随着数据的增加时时保持更新:
- $ tail -f growing_file
这种文件内容会不断增加的典型例子就是日志文件。用于监视文件内容增加的命令如下:
- # tail -f /var/log/messages
或者
- $ dmesg | tail -f
我们不时会运行dmeg
查看内核的环形缓冲区(kernel ring buffer)消息,要么是调试USB设备,要么是查看sdX
(X是sd设备的次序列号)。tail -f
也可以加入一个睡眠间隔 -s
,这样我们就可以设置监视文件更新的时间间隔。
tail
具有一个很有意思的特性:当某个给定进程结束之后,tail
也会随之终结。
假设我们正在读取一个不断增长的文件,进程Foo
一直在向该文件追加数据,那么tail -f
就会一直执行,直到进程Foo
结束。
- $ PID=$(pidof Foo)
- $ tail -f file --pid $PID
当进程Foo
结束之后,tail
也会跟着结束。
让我们实际演练一下。
创建一个新文件file.txt,用gedit
打开这个文件(你也可以使用其他文本编辑器)。
向文件添加新内容并不断地将它们保存到gedit
中。
现在运行:
- $ PID=$(pidof gedit)
- $ tail -f file.txt --pid $PID
当你不断对文件进行更新时,更新的内容都会被tail
命令写入终端;当关闭gedit
时,tail
命令也会结束。