70

I want to output a file's contents while they change, for example if I have the file foobar and I do:

magic_command foobar

The current terminal should display the file's contents and wait until, I don't know, I press ^C.

Then if from another terminal I do:

echo asdf >> foobar

The first terminal should display the newly added line in addition to the original file contents (of course, given that I didn't press ^C).

1

5 Answers 5

113

You can use tail command with -f :

tail -f /var/log/syslog 

It's good solution for real time show.

2
  • you can write a script and redirect your output to your script. Aug 16, 2012 at 20:11
  • 6
    You can also use -F (capital f), which will reopen the file if it gets removed and recreated along the way.
    – peterph
    Sep 25, 2013 at 20:49
29

If you want to show a short file, that fits on one terminal screen, and what is changing is possibly the whole file, you could use watch:

watch cat example.txt

Every 2.0s: cat example.txt                                Sun Aug  3 15:25:20 2014

Some text
another line

It shows the whole file every 2 seconds by default, including an optional header:

The option -d (--differences) will highlight changes from previous version of the output, or from the first version.

11

less has a follow mode similar to tail -f - just hit F when you have it open.

3
  • 1
    You can also do less +F filename (yes, +F, not -F)
    – c-x-berger
    Feb 21, 2020 at 6:57
  • @c-x-berger can you provide link to documentation please (man page is silent on this topic for me)?
    – peterph
    Feb 27, 2020 at 22:19
  • 1
    stackoverflow.com/a/6143944/3551604 is where i first saw it.
    – c-x-berger
    Feb 28, 2020 at 2:39
9

When I need to detect file changes and do something other than what tail -f filename does, I've used inotifywait in a script to detect the change and act upon it. An example of use is shown below. See man inotifywait for other event names and switches. You may need to install the inotify-tools package, for example via sudo apt-get install inotify-tools.

Here's the example script, called exec-on-change:

 #!/bin/sh

# Detect when file named by param $1 changes.
# When it changes, do command specified by other params.

F=$1
shift
P="$*"

# Result of inotifywait is put in S so it doesn't echo
while  S=$(inotifywait -eMODIFY $F 2>/dev/null)
do
  # Remove printf if timestamps not wanted 
  printf "At %s: \n" "$(date)"
  $P
done

In two consoles I entered commands as follows (where A> means entry in console A, and B> means entry in console B.)

A> rm t; touch t
B> ./exec-on-change t wc t
A> date >>t
A> date -R >>t
A> date -Ru >>t
A> cat t; rm t

The following output from cat t appeared in console A:

Thu Aug 16 11:57:01 MDT 2012
Thu, 16 Aug 2012 11:57:04 -0600
Thu, 16 Aug 2012 17:57:07 +0000

The following output from exec-on-change appeared in console B:

At Thu Aug 16 11:57:01 MDT 2012: 
 1  6 29 t
At Thu Aug 16 11:57:04 MDT 2012: 
 2 12 61 t
At Thu Aug 16 11:57:07 MDT 2012: 
 3 18 93 t

The exec-on-change script terminated when I rm'd t.

0
4

I have three solutions:

1) tail -f is a good idea

2) we have also tailf to use

3) third one is a bash script:

#!/bin/bash

GAP=10     #How long to wait
LOGFILE=$1 #File to log to

if [ "$#" -ne "1" ]; then
    echo "USAGE: `basename $0` <file with absolute path>"
    exit 1
fi


#Get current long of the file
len=`wc -l $LOGFILE | awk '{ print $1 }'`
echo "Current size is $len lines."

while :
do
    if [ -N $LOGFILE ]; then
        echo "`date`: New Entries in $LOGFILE: "
        newlen=`wc -l $LOGFILE | awk ' { print $1 }'`
        newlines=`expr $newlen - $len`
        tail -$newlines $LOGFILE
        len=$newlen
    fi
sleep $GAP
done
exit 0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.