inotifywait different action on file or dir

5,523

Solution 1

The following works for me:

Example

Below shows an example of inotifywait using a method similar to your own.

$ inotifywait -r -e close_write "somedir" | while read f; do echo "$f hi";done
Setting up watches.  Beware: since -r was given, this may take a while!
Watches established.    

I then go into the directory somedir and touch afile, touch afile. Which results in this occurring in the inotifywait window:

somedir/ CLOSE_WRITE,CLOSE afile hi

NOTE: To get all the output from inotifywait you could modify your example slightly:

$ inotifywait -r -e close_write "somedir" 2>&1 | \
    while read f; do echo "$f | hi";done
Setting up watches.  Beware: since -r was given, this may take a while! | hi
Watches established. | hi

And again touch a file with the command, touch afile, I now see the event:

somedir/ CLOSE_WRITE,CLOSE afile | hi

For another example that shows how to use inotifywait take a look at the example I showed in my answer to this Q&A titled: Automatically detect when a file has reached a size limit.

Your issue

I believe part of your issue is that you're assuming that the output returned from inotifywait is just the file's name while clearly it isn't from the above examples.

So these if statements will never succeed:

  if [[ -d "${f}" ]]; then

and

  if [[ -f "${f}" ]]; then 

When developing Bash scripts such as this it's often helpful to enable debugging messages via this command at the top:

set -x

You can disable it with this:

set +x

You can wrap sections of your code using these messages to turn it on/off.

set -x
...code...
set +x

Solution 2

Got it working thanks to the info slm provided :-)

#!/bin/bash

# Written by Jan Duprez and licensed as
# do whatever you want with this but don't come whining
# if you somehow manage to trash your system with it.
# You pressed the buttons, remember?

# This script uses inotifywait to watch a directory and copies
# files or directories moved into it to another folder.

# The commandline parameters are:
# 1 - Directory to watch
# 2 - Directory where new file/folder is copied to
# 3 - UID to use to chmod the file/folder in BOTH dirs
# 4 - GID to use to chmod the file/folder in BOTH dirs
# 5 - permissions to set for the new file/folder in BOTH dirs

dir1=$1
dir2=$2
user=$3
group=$4
perms=$5

# Check if commandline parameters are all there, show reminder if not
if [[ -z $dir1 || -z $dir2 || -z $user || -z $group || -z $perms ]];
then    
    echo -e "Please provide a source dir as 1st parameter"
            echo -e "Please provide a dest dir as 2nd parameter"
            echo -e "Please provide a UID as 3rd parameter"
            echo -e "Please provide a GID as 4th parameter"
            echo -e "Please provide a file permission string (ex 755) as 5th parameter"
    exit
fi

# Good to go, start watching
while true; do

#add -e close_write and -e create for testing
inotifywait -r -e move "$dir1" | while read f; do

#Get part after inotify triggers with awk, remove leading spaces with sed
new=`echo $f | awk '{$1=$2=""; print $0}' | sed 's/^ *//'`
#And the preconstruded full path to avoid ugly buggery between the  [[ ]]    test
test=$dir1$new

    if [[ -d "${test}" ]] ; then
    chown -R $user:$group "$dir1$new"
    chmod -R $perms "$dir1$new"
    cp -R "$dir1$new" "$dir2"
    chown -R $user:$group "$dir2$new"
    fi

    if [[ -f "${test}" ]] ; then
    chown $user:$group "$dir1$new"
    chmod $perms "$dir1$new"
    cp "$dir1$new" "$dir2"
    chown $user:$group "$dir2$new"
    fi
done
done
Share:
5,523

Related videos on Youtube

Jake
Author by

Jake

Updated on September 18, 2022

Comments

  • Jake
    Jake over 1 year

    I'm trying to make a inotifywait script take different actions for files vs folders if it sees a close_write flag being raised in the watched directory, but cannot seem to get the checks working.

    In other scripts I use these kinds of checks all the time and they just_work, but there seems to be something about inotifywait I'm not grasping yet.

    This is the script in its current form:

        #!/bin/bash
    
        dir1=/sambashares
    
        while true; do
         inotifywait -r -e close_write "$dir1" | while read f; do
          #debug
          echo $f
          #Is it a directory?
          if [[ -d "${f}" ]]; then
           #debug
           echo "New directory called ${f} detected"
           chown -R jake:jake $f
           chmod -R 775 $f
           cp -R $f /media/lacie/Film
          fi
          #Is it a file?
          if [[ -f "${f}" ]]; then 
          #debug
          echo "New file called ${f} detected"
          chown jake:jake $f
          chmod 775 $f
          cp $f /media/lacie/Film
          fi
    
         done
        done
    

    If I run this in a terminal to see what is happening all I get is the confirmation a close_write was detected, followed by a "setting up watches" without any other messages or any of the other code being triggered, not even the debug echo directly below:

     while read f; do
    

    :-(

    I'm running this on Ubuntu server 12.04 LTS 64 bit.

    $ bash --version
    GNU bash, version 4.2.25(1)-release (x86_64-pc-linux-gnu)
    
    $ dpkg -l | grep inotify
    ii  inotify-tools                    3.13-3
    ii  libinotifytools0                 3.13-3
    ii  python-pyinotify                 0.9.2-1
    
    $ python --version
    Python 2.7.3
    
  • Jake
    Jake almost 10 years
    Thanks for pointing out the debug option in bash, i did not know about this and it will help me a lot in the future.