2

I am looking to monitor content changes within a file and when that content changes, produce a notification displaying the new text.

Details

Let us say the file (connection.txt) contained only the words "You are connected to the internet".

However, when the computer disconnects from the internet, the contents of the file change to "You are now disconnected from the internet".

How would you monitor the contents of the file and, only when the contents change, display the new text in a desktop notification (I am using Manjaro).

To add to the problem, this file is updated every four seconds, often with exactly the same text.

My research

I have searched for solutions to this with no avail. I have found many examples of monitoring files and directories for event changes such as files created, modified or deleted, but nothing on real-time monitoring of text inside a file.

If this is possible, are there similar techniques for monitoring changes to the output of a command?

1
  • I'll guess you need two tools to do this - perhaps watch to catch the changes, and diff to report what changed.
    – Seamus
    Nov 11, 2020 at 2:47

3 Answers 3

3

For the general case you want to monitor a file, and send a desktop notification with the new file content only when the content has changed, you can use inotifywait (from inotify-tools) with the -m, --monitor option to execute indefinitely.

--format "%e" will print only the type of the event to the next command.

notify-send, from libnotify for desktop notifications, is being used to send the notification only if the file content is modified.

#!/bin/bash

f="filename"
curr=$(<"$f")

inotifywait -m -e modify "$f" --format "%e" | while read -r event; do
    if [ "$event" == "MODIFY" ]; then
        prev="$curr"
        curr=$(<"$f")
        [ "$curr" == "$prev" ] || notify-send "Title" "$curr"
    fi
done

For your specific case, I would not monitor changes to files, if your goal is to display a desktop notification with a text like "you are connected" or "you are disconnected". I would modify the place where you print that text (every N seconds as you say) into that file, to something like this:

while true; do
    prev="$curr"
    curr=$( <here you output the new text> )
    [ "$curr" == "$prev" ] || notify-send "Title" "$curr"
    sleep 4
done
2

I would like to share a skeleton code. You might expand on this idea.

#!/bin/bash 

# monitor_changes
#
#     notifies changes to FILE passed as first parameter $1
#     uses tail -1 to return last line of the file

# first run -- save last line on variable old
old=$(tail -1 $1) 

# infinite loop 
while : ; do
    sleep 1
    # read again last line
    new=$(tail -1 $1) 

    # this is where the magic should happen
    [[ "$old" != "$new" ]] && echo "NOTIFY: $old --> $new"

    # save for next round
    old=$new
done

2
  • Thank you Jayr, I'll give this a try and feedback my results. Nov 11, 2020 at 6:48
  • I did manage to make this work. Not too tricky for me to understand either, which is a bonus. I used notify-send instead of echo for desktop notifications. The end result is a little temperamental, but I think this is the result of one of my other scripts. Nov 13, 2020 at 1:41
2

inotify to catch the (potential) changes. Just because the file is modified, does not mean that is is changed.

make to act of file changes. It works with file date, so this needs to be reliable. You also need an output file, this can be a dummy that you create after writing to the screen.

Other tools to do the 2nd part: e.g. Using file hashes (instead of dates), if the file is small, keeping a copy and using cmp.

an example of usage

#!/bin/bash

while true
do
    inotify-wait --event modify source-file.txt
    make $(basename source-file .txt).stamp
    #there is a race hazard here: if the file changes again before we get back to the wait, then it may not be picked up.
done
# A make file template
%.stamp: %.txt
«tab» do_it $<
«tab» touch $@

Replace «tab» with a tab. Replace do_it with the code that does it. The $< will be replaced with the source file-name.

5
  • Thank you for this @ctrl-alt-delor. As I am not overly familiar with these programs, could you demonstrate how I might use them to acheive these goals? Nov 11, 2020 at 20:04
  • I added some code, but there is a bug: a race condition. Nov 12, 2020 at 19:22
  • Apologies for my naivety, but what is a race hazard/condition? Nov 13, 2020 at 1:37
  • A race hazard is where the outcome depends on timing: what happens first. In my above code if the file changes between make ending (and may be at bit before that) and inotify starting then nothing will happen (you could end up waiting forever). After getting it to work then it would be worth a question, to ask how to eliminate the race condition. Hazard: because it can cause problems. Condition: is what it does when it looses the race (if A is before B then … else …) Nov 13, 2020 at 17:40
  • Ahh... Makes sense. Thanks for the explanation! Nov 13, 2020 at 23:31

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .