Output file contents while they change

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).

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

You can use tail command with -f :

tail -f /var/log/syslog 

It’s good solution for real time show.

Solution 2

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.

Solution 3

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

Solution 4

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.

Solution 5

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

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply