none
none

Reputation: 12117

clear screen when the file is truncated while using `tail -f`

I'm using tail -f to print the content of a continuously changing file. When the file is truncated it shows up like this:

blah (old)..
blah more (old)..
tail: file.out: file truncated
blah..
blah more..

This can get messy when I change the file too often so that it becomes hard to see where the file begins/ends. Is there a way to somehow clear the screen when the file is truncated so that it would show up like this?

tail: file.out: file truncated
blah..
blah more..

Upvotes: 10

Views: 5748

Answers (4)

agentcd
agentcd

Reputation: 1

In case anyone else finds their way here more than 11 years later, I've written a somewhat more complicated bash script to do what I want (monitoring a log file) based on watching for size changes:

#!/usr/bin/bash
set -e

FILE="$1"
#TODO verify $FILE is valid

LAST=0
while SIZE="$(stat -c '%s' "$FILE")"; do
  # This will only trigger due to a race condition, since stat would normally fail
  if [ "$event" = "DELETE_SELF" -o "$event" = "MOVE_SELF" ]; then
    echo "Watch interrupted: file moved or deleted" 1>&2
    exit 1
  fi
  # Small files might be overwritten without us ever seeing a smaller size
  # To be safe, just print out everything again since it's not that much
  if [ "$LAST" -le 2048 -o "$SIZE" -lt "$LAST" ]; then
    clear
    LAST=0
  fi
  if [ "$LAST" -lt "$SIZE" ]; then
    # tail -c +N is 1-based!
    tail -c "+$((LAST + 1))" "$FILE" | head -c "$(( SIZE - LAST ))"
    LAST="$SIZE"
  fi
  read event
done < <(inotifywait -qme 'modify,close_write,delete_self,move_self' --format '%e' "$FILE")

It requires inotifywait from the inotify-tools package. Alternatively, the monitored file can be checked periodically with sleep. Simply replace the last 2 lines with the following:

  sleep 1
done

When using sleep instead of inotify, missing a truncate becomes more likely since the file size isn't checked immediately after each write. In exchange, there are no requirements beyond coreutils + clear, and many small writes to the monitored file don't cause increased resource usage.

Advantages:

  • Unlike watch, the file content is not interpreted, and terminal colors remain intact
  • Unlike Benj's perl one-liner, the file content itself can not cause a clear

Disadvantages:

  • When instantly overwriting a file larger than the 2048 byte threshold, the truncate may go unnoticed. Therefore, this script doesn't work well when monitoring a text file being edited.
  • Each write to the file causes one execution of stat, tail and head each

Note: When using inotifywait, moving or deleting the file will cause the script to exit. Some text editors do this (vim for example).

For more discussion on inotifywait, see this question on superuser.com

Upvotes: 0

Rhys
Rhys

Reputation: 1491

I know this is old, but another (potentially simpler) solution is:

watch -n 1 cat myfile.txt

Upvotes: 15

V H
V H

Reputation: 8587

tailf myfile.txt

this is the command tailf rather than tail -f

with this command there is no file truncated returned on the screen

Upvotes: 1

Benj
Benj

Reputation: 32418

You could use a perl one-liner to filter the output from tail -f

e.g.

tail -f myfile.txt 2>&1 | perl -ne 'if (/file truncated/) {system 'clear'; print} else {print}'

Upvotes: 10

Related Questions