12

I'm trying to find a way to immediately move a file to another folder as soon as it appears in my dropbox on CentOS.

I have scoured the internet for some clues but I can't get any further than the fact that I need to use inotify to invoke a script which will process the file as it appears.

My BASH knowledge is very limited and I doubt I can write this in PHP.

In other words, how can I move a file to another folder as soon as it appears using inotify?

jasonwryan
  • 73,126
Ortix92
  • 287
  • Is the name of the file consistently predictable? Or it's location? More detail would be helpful... – jasonwryan Aug 10 '13 at 22:07
  • @jasonwryan It's a dropbox folder so the location is consistent. And it applies to any file dropped in that folder. – Ortix92 Aug 10 '13 at 22:14

2 Answers2

20

The command inotifywait prints a message each time a the contents of the specified directory change. You'll need to pick on the right event: not when the file is created, but when Dropbox has finished downloading it. I don't know exactly how Dropbox operates. If it writes to the file in its final place, listen to close_write events. If it writes to the file into a temporary location and then moves it into place, listen to moved_to events. Pass the options -m -q to inotifywait so that it keeps listening for events (by default, it only waits for the next event) and only prints relevant messages.

cd ~/Dropbox/myfolder
inotifywait -m -q -e close_write --format %f . | while IFS= read -r file; do
  cp -p "$file" /path/to/other/directory
done
  • 2
    This fails for files which include newlines in their names. I was unable to find a way to have inotifywait output null-terminated filenames. The best I could do was to use a character that's less likely than newline, for example %f$'\001', and use -d $'\001' with while IFS= read -r or xargs. – Dennis Williamson Nov 03 '15 at 22:48
  • 2
    @DennisWilliamson Yes, inotifywait is annoying that way. You can use something like //%f, as the file name will never contain a double slash as long as the path to watch doesn't; then the annoyance is on the parsing side. – Gilles 'SO- stop being evil' Nov 03 '15 at 22:53
13

This is a simple approach:

#!/usr/bin/env bash

dir=/home/ortix/Dropbox/new/
target=/home/ortix/movedfiles/

inotifywait -m "$dir" --format '%w%f' -e create |
    while read file; do
        mv "$file" "$target"
    done

With more details about the types of files you wanted to move, you could add some checking, logging etc...

jasonwryan
  • 73,126
  • I haven't been able to test either of the suggested answers. Things came up. Will do so ASAP! I do have a question though. If I were to put this in a bash file and run it, I assume that it will run in the background, correct? I always have the feeling that a script is a 1 time run thing, but here inotifywait keeps running, correct? – Ortix92 Aug 14 '13 at 19:09
  • 3
    listening on create event isn't correct, as you will do a mv on a file which may not be fully copied on disk. See @Gilles answer, using close_write event instead. – fduff Jun 26 '14 at 07:57
  • 3
    @fduff Seeing Gilles answer is always the correct thing to do... – jasonwryan Jun 26 '14 at 08:00