## 12.10. How to Look at Files as They Grow

One of the best things that you can do with tail is to look at a file as it is growing. For example, I once was debugging a program named totroff that converted a manual from a plain text format to troff. It was rather slow, so that you didn't want to wait until the program finished before looking at the output. But you didn't want to be typing `more` every 20 seconds either, to find out whether the part of the file that you were debugging had made it through yet. (more quits when you "run out" of file, so it can't really help you look for a part of a file that hasn't been written yet.) The tail -f command solves this problem. For example:

`&` Section 23.3

>     % totroff < file.txt > file.ms &
>     [1] 12345
>     % tail -f file.ms
>     .LP
>     Tail produces output as
>     the file grows.
>        ...
>     CTRL-c

Now suppose you want to monitor several files at once. Administrators, for example, might want to keep track of several log files, such as /usr/adm/messages, /usr/adm/lpd-errs, UUCP error files, etc. The GNU tail program comes in useful for keeping an eye on several administrative log files at once. But it also comes in useful for nonadministrators.

For example, suppose you want to perform several greps through many files, saving the output in different files. You can then monitor the files using tail -f. For example:

>     % grep Berkeley ch?? > Berkeley.grep &
>     % grep BSD ch?? > BSD.grep &
>     % grep "System V" ch?? > SystemV.grep &
>     % grep SysV ch?? > SysV.grep &
>     % tail -f Berkeley.grep BSD.grep SystemV.grep SysV.grep

When new text appears in the files called with tail -f, it also appears on the screen:

>     ==> SysV.grep <==
>     ch01:using a SysV-based UNIX system, you must

>     ==> Berkeley.grep <==
>     ch01:at the University of California at Berkeley, where

>     ==> BSD.grep <==
>     ch03:prefer BSD UNIX systems because they are less likely to
>     ch04:who use a BSD-based UNIX systems must run the

>     ==> SysV.grep <==
>     ch04:is a SysV derivative sold by Acme Products Inc.

(When text is written to a new file, the filename is printed surrounded by `==>` and `<==`.)

What's actually happening here?

When you invoke tail -f, tail behaves just like it normally does: it reads the file and dumps the last ten (or however many) lines to the screen. But, unlike most applications, tail doesn't quit at this point. Instead, tail goes into an infinite loop. It sleeps for a second, then wakes up and looks to see if the file is any longer, then sleeps again, and so on. Because this is an infinite loop, you have to enter CTRL-c (or whatever your interrupt key (Section 24.11) is) when you've seen the data you're interested in, or when the file you're watching has been completed. tail has no way of knowing when the file has stopped growing.

tail ignores the -f option when it is reading from a pipe. For example, totroff < file.txt | tail -f wouldn't work.

Section 12.11 shows a useful feature of GNU tail: following files by name or file descriptor.

--ML and LM

Copyright © 2003 O'Reilly & Associates. All rights reserved.