One of the best things that you can do with tail is 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 running before looking at the output. But you didn't want to be typing every 20 seconds either, to find out whether or not 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:
Other applications for tail -f: lets you watch any system log file (/usr/adm/messages, sendmail log file, news log, etc.) as it grows.
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 whatever) 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 youris) 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.