0

I am monitoring a folder ($WATCHED) for new files (only .mkv)/folders. When something shows up it is to copy them to a Destination folder ($DESTINATION) and then change the ownership and permissions.

Here is the script I am using.

#!/bin/bash

WATCHED=/mnt/Watched
DESTINATION=/mnt/Destination
user=usrid
group=grpid
perms=755

inotifywait -re CLOSE_WRITE,CREATE,MOVED_TO --format $'%e\t%w%f' -m $WATCHED |
    while IFS=$'\t' read -r events new
    do

# Detecting and copying new files/folders

        sleep 5
        if [[ -d "$new" ]]
        then
            echo "Folder Detected: $new, Copying to Destination folder"
            cp -r "$new" "$DESTINATION/"
        elif [[ "$events" =~ CLOSE_WRITE ]]
        then
            if [ -f "$new" ] && [ "${new##*.}" == mkv ]
            then
                echo "File Detected: $new, Copying to Destination folder"
                cp -r "$new" "$DESTINATION/"
            elif [[ -e "$new" ]]
            then
                echo "New unknown item '$new'"
            fi
        fi

        echo "Changing ownership and permissions for $DESTINATION"
        chown -R $user:$group "$DESTINATION"
        chmod -R $perms "$DESTINATION"
        echo


    done

I am having a couple of issues with this script.

  • The changing ownership/permissions run three times for some reason when there is only one folder and one file in the folder. You can see from the output below that the second instance of this is by itself. Not sure why? I know that my placement and action for this is incorrect for what I would like to achieve. I would prefer that the ownership/permissions are done for each new individual file/folder when they are copied and not the entire destination folder. I am not sure the correct way of changing the ownership/permissions on each new file/folder only. Any guidance here would be very much appreciated.
  • This script copies the folder and file to the directory using the correct/same directory tree BUT it also copies the file to the destination folder as well. So I have two copies of the file. First, why is it making a copy directly in the destination folder, and second, how do I stop it from doing that?

Here is the output.

Folder Detected: /mnt/Watched/NewFolder, Copying to the Destination folder
Changing ownership and permissions for /mnt/Destination

Changing ownership and permissions for /mnt/Destination

File Detected: /mnt/Watched/NewFolder/NewFile.mkv, Copying to Destination folder
Changing ownership and permissions for /mnt/Destination

This is how I would like the output to look

Folder Detected: /mnt/Watched/NewFolder, Copying to the Destination folder
Changing ownership and permissions for /mnt/Destination/NewFolder

File Detected: /mnt/Watched/NewFolder/NewFile.mkv, Copying to Destination folder
Changing ownership and permissions for /mnt/Destination/NewFolder/NewFile.mkv

Thanks

1
  • 1
    Why doesn't my answer on your almost identical question work for you? Extend the echo "New file '$item'" line to perform your mkdir, cp, chown, chgrp. Stop trying to copy a directory with its files when (only) the directory has been created - let the events for each file tell you when they're ready to be copied. In fact, don't even bother catching directory creation events - just create intermediate directories when you copy a file. – roaima Dec 20 '20 at 9:55
0

You're looking for both CREATE and CLOSE_WRITE events, but not separating between them in the code.

When a new file appears, it quite likely generates both of those events, first "CREATE" when the file is initially created, and then "CLOSE_WRITE" when it's closed after being actually written to.

A "CREATE" event on a file will not catch any of the branches of your if statement, but will only run the "Changing ownership and permissions..." part.

You need to decide what you want to do for each event, probably for files and directories separately. The "CREATE" event for files is probably not very interesting as that would happen without a "CLOSE_WRITE" only if a file is created without being opened for writing. (That can happen if someone calls open(filename, O_CREAT|O_RDONLY) on purpose, but even touch doesn't do that.)

I suggest you add a line to print the events as they're received, so you can see what the code actually gets, e.g.:

while IFS=$'\t' read -r events new
do
    echo "get event: $events on file $new"

I'm also not at all sure why you're calling sleep 5 there in the loop; it doesn't seem to do anything but delay the script.

8
  • 1
    Thank you for reiterating this. It was already handled in my answer to the OP's almost identical question :-( – roaima Dec 20 '20 at 17:49
  • Thanks ilkakachu and roaima! I have taken information from both of your suggestions and dissected my code and came to the realization that I was making it more complicated than it needed to be. I ended up stripping out all but one of the IF statements and used rsync to copy my files. I now have it working exactly as I wanted. – S. Ray Dec 21 '20 at 3:22
  • The sleep 5 was because I felt like the script started running before files were actually copied into the watch folder. It seemed that having that 5 second wait helped in some situations. I have removed it in my new script. – S. Ray Dec 21 '20 at 3:22
  • 1
    @roaima, I started wondering if I should have just read your answer more closely and closed this as a duplicate, but I guess the important thing is that the problem got solved. – ilkkachu Dec 21 '20 at 9:39
  • @S.Ray, hmm, yes, rsync is the easy way out, though of course it's a bit of a big hammer compared to inotify. I just realized another problem here, that you can get paths as the output of inotify, as in, if you're watching at /foo, the path in the notification can be /foo/sub/file.mkv, and if you want to keep the directory structure, you'd need to do take that into account at the cp. Might just be enough to do cp "$new" "$dest/$new", or not... – ilkkachu Dec 21 '20 at 9:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.