Giova84
Giova84

Reputation: 45

Folder Watcher bash script: also check for subfolders

EDIT:

I've improved this "FolderWatcher script" of user konsolebox (from the answer below: https://stackoverflow.com/a/18597233/2095175 ) I have added these lines to automatically move every kind of file in a right folder on my system (eg pdf in /Docs folder, Images in /Picture and video files in /Videos)

extension=${ADDED##*.}
if [ "$extension" = "xz" ] || [ "$extension" = "zip" ] || [ "$extension" = "gz" ] || [ "$extension" = "bz2" ] || [ "$extension" = "7z" ]; then
open $ADDED
fi
if [ "$extension" = "pdf" ] || [ "$extension" = "txt" ] || [ "$extension" = "odt" ] || [ "$extension" = "doc" ] ; then
mv "$ADDED" /boot/home/Docs
alert --idea " $ADDED moved to /boot/home/Docs"
open /boot/home/Docs
fi
if [ "$extension" = "jpg" ] || [ "$extension" = "png" ] || [ "$extension" = "gif" ]; then
mv "$ADDED" /boot/home/Media/Images
alert --idea " $ADDED moved to /boot/home/Media/Images"
open /boot/home/Media/Images
fi
if [ "$extension" = "flv" ] || [ "$extension" = "avi" ] || [ "$extension" = "mp4" ] || [ "$extension" = "mpg" ]; then
mv "$ADDED" /boot/home/Media/Video
alert --idea " $ADDED moved to /boot/home/Media/Video"
open /boot/home/Media/Video
fi

ORIGINAL QUESTION:

i have the following script which continuously check for the content of a folder, and alert me whenever a new file is inserted and/or when is deleted. Works perfectly as expected. But doesn't check subfolders in the main folder ( folder=$(cat /boot/home/FolderWatcher_pref.txt) ) Eg if I insert/remove file from the main folder, i will be alerted, but if i insert/remove files in a subfolder of "$folder", the script is not able to alert me. What can i change or add in this script to achieve this need?

I am on Haiku OS, so some command like "alert" are Haiku-specific.


    #!/bin/bash                                                                                                                                                                                         

    cat /dev/null > $difffile1
    cat /dev/null > $difffile2

    #The path where to look is set in a text file, which i can change with a file panel to select any folder
    folder=$(cat /boot/home/FolderWatcher_pref.txt) 
    tstamp=$(stat --print "%Y" "$folder")

    while true; do
    prev=$(ls "$folder" | tr '\n' '\n'  > /tmp/prev.txt)
    sleep 5

    if [[ "$folder" == "$folder" && $tstamp -lt $(stat --print "%Y" "$folder") ]]; then
    after=$(ls "$folder" | tr '\n' '\n'  > /tmp/after.txt)


    difference1=$(comm -2 -3 "/tmp/after.txt" "/tmp/prev.txt">/tmp/Diff.txt)
    added=$(cat /boot/common/cache/tmp/Diff.txt)


    difference2=$(comm -2 -3 "/tmp/prev.txt" "/tmp/after.txt">/tmp/Diff2.txt)
    lost=$(cat /boot/common/cache/tmp/Diff2.txt)


    difffile1=/tmp/Diff.txt
    difffile2=/tmp/Diff2.txt
    FILESIZE2=$(stat -c%s "$difffile2")
    if [ "$FILESIZE2" == 0 ]
    then 
    lost=nothing
    fi
    FILESIZE1=$(stat -c%s "$difffile1")
    if [ "$FILESIZE1" == 0 ]
    then 
    added=nothing

    fi

    lost2=$(cat /boot/common/cache/tmp/Diff2.txt)
    alert --idea "$folder:

    $added
    *INSERTED*.

    $lost
    *REMOVED*."; 

    echo "$lost2" >>$folder/Removed.txt

    tstamp=$(stat --print "%Y" "$folder")

    cat /dev/null > $difffile1
    cat /dev/null > $difffile2
        else                                                                                                                                                                                            
            sleep 3;                                                                                                                                                                                    
        fi                                                                                                                                                                                              
    done

Upvotes: 1

Views: 552

Answers (3)

konsolebox
konsolebox

Reputation: 75588

I end up making my own modification but this one works and no longer uses temporary files. It uses find and process substitution.

#!/bin/bash

[ -n "$BASH_VERSION" ] && [[ BASH_VERSINFO -ge 3 ]] || {
    echo "You need bash version 3.0 or newer to run this script." >&2
    exit 1
}

shopt -s extglob

FOLDER=$(</boot/home/FolderWatcher_pref.txt)
REMOVED_LOG="$FOLDER/Removed.txt"  ## It's better to place this somewhere not in "$FOLDER" to not confuse timestamps everytime it is updated.

if [[ ! -d $FOLDER ]]; then
    echo "Directory does not exist: $FOLDER" >&2
elif read TIMESTAMP < <(exec find "$FOLDER" -type d -printf "%T@\n" | cut -f 1 -d . | sort -nr); [[ $TIMESTAMP != +([[:digit:]]) ]]; then
    echo "Unable to get timestamp of directory: $FOLDER" >&2
else
    STATE=$(exec find "$FOLDER" -mindepth 1 | sort)

    for (( ;; )); do
        sleep 5

        if [[ -d $FOLDER ]] && read NEWTIMESTAMP < <(exec find "$FOLDER" -type d -printf "%T@\n" | cut -f 1 -d . | sort -nr) && [[ NEWTIMESTAMP -gt TIMESTAMP ]]; then
            NEWSTATE=$(exec find "$FOLDER" -mindepth 1 | sort)

            ADDED=$(comm -2 -3 <(echo "$NEWSTATE") <(echo "$STATE"))
            [[ -z $ADDED ]] && ADDED='nothing'

            LOST=$(comm -2 -3 <(echo "$STATE") <(echo "$NEWSTATE"))
            LOST_ORIG=$LOST
            [[ -z $LOST ]] && LOST='nothing'

            alert --idea "$FOLDER:

$ADDED
*INSERTED*.

$LOST
*REMOVED*."

            [[ -n $LOST_ORIG ]] && echo "$LOST_ORIG" >> "$REMOVED_LOG"

            read TIMESTAMP < <(exec find "$FOLDER" -type d -printf "%T@\n" | cut -f 1 -d . | sort -nr) && [[ TIMESTAMP -ge NEWTIMESTAMP ]] || TIMESTAMP=$NEWTIMESTAMP
            STATE=$NEWSTATE
        fi
    done
fi

Upvotes: 1

Aleks-Daniel Jakimenko-A.
Aleks-Daniel Jakimenko-A.

Reputation: 10673

Why can't you use inotifywait or inotifywatch ? You can use -r flag to make it recursive. Take a look at inotify-tools.
You may be interested in incron as well.

Upvotes: 1

Paul Evans
Paul Evans

Reputation: 27577

You want to augment this line:

prev=$(ls "$folder" | tr '\n' '\n'  > /tmp/prev.txt)

to something like:

prev=$(ls "$folder"/* | tr '\n' '\n'  > /tmp/prev.txt)

Upvotes: 0

Related Questions