0

I'm using Ubuntu 20.04. I'm trying to run this script for inotifywait. The idea is to move files from dir to target every time a change in directory occurs; this script is a shell file that can be started automatically or manually via the command line.

#!/usr/bin/env bash
dir=/mnt/test1/test/ #ftp point of mount
target=/var/www/html/local/ #normal directory on filesystem

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

And files to move need to have the *.txt format. inotify is watching, but when I use my ftp client to put a file in dir and wait for inotify to move it to target, nothing happens with the file.

I am using this for reference: https://unix.stackexchange.com/a/86292/425161

fra-san
  • 10,205
  • 2
  • 22
  • 43
  • Have you read the answers to that question you linked? Because you're listening for the creation of a file. When the file is first created, it's going to be empty. – Andrew Henle Jul 30 '20 at 19:15
  • @AndrewHenle yes i have create the file in and out of the directory to test all event posible that trigger; and i have use move_to to try when i drop the file via ftp, but not working i have the mount point dir with this guide: https://wiki.archlinux.org/index.php/CurlFtpFS and work well, but i dont know if becouse it is a mount point not have event in local file system... –  Jul 30 '20 at 19:55
  • @FranciscoNúñez I took the liberty to edit your question, trying to make it more clear. Feel free to revert my changes if they diverged from your original intent. – fra-san Jul 31 '20 at 11:36

1 Answers1

1

Unfortunately, the inotify API can not be used to monitor remote file systems.

From man 7 inotify:

Inotify reports only events that a user-space program triggers through the filesystem API. As a result, it does not catch remote events that occur on network filesystems. (Applications must fall back to polling the filesystem to catch such events.)

Relating questions:

That said, the script in your question would not work as expected anyway.

The idea of using "%w%f" as the format of inotifywait's output is to provide the command in the loop with the full path of files that triggered a listened-for file system event. %w expands to the path of the watched file (the $dir directory), and %f expands to the (base)name of the file that caused the event.

Thus, inotifywait is only emitting a single full path for every event it catches. On the other hand, your read command is given three variables to fill in: path, action and file. By default, read splits a read line based on the characters in IFS and assigns the resulting tokens to the names it is given as arguments: the first token to the first name, the second token to the second name, etc. (And, if there are more tokens than names after the penultimate name, all the remaining tokens are assigned to the last name).

As you can easily check, in your code the full path of any file that trigger a watched-for event is assigned to path (unless it contained blank characters):

$ inotifywait -m --format "%w%f" -e create -e moved_to /tmp/test |
  while read path action file; do
    printf 'path: "%s"; action: "%s"; file: "%s"\n' "$path" "$action" "$file"
  done
# Type "touch /tmp/test/foo" in a different terminal
path: "/tmp/test/foo"; action: ""; file: ""

Also, as pointed out in a different answer in the Q/A you inked to, you should listen for close_write events, and not for create. What you are probably looking for is:

inotifywait -m -q --format "%w%f" -e close_write -e moved_to -- "$dir" |
  while IFS= read -r src; do
    if [ "${src##*.}" = 'txt' ]; then
      mv -- "$src" "$target"
    fi
  done

-r tells read not to interpret backslash-escaped sequences. IFS= is used to prevent read from trimming blank characters from the end of file names (to handle the unlikely case of names ending with spaces or tabs).

Note that this will still fail for files whose name contains newline characters.

fra-san
  • 10,205
  • 2
  • 22
  • 43
  • but then; I need to monitor an FTP mount point; if inotify is not able to do it; that another tool has linux / ubuntu that can do it; I really don't want to use a cron that runs every minute; Is there a way to create a Service that monitors the modification of this directory which is an FTP mount point ??? –  Aug 01 '20 at 15:15
  • 1
    @FranciscoNúñez I'm not aware of any tool capable of that, sorry (this doesn't mean it doesn't exist, of course ;-). The inotify manual mentions the need to resort to polling, leading me to think there is no well-known/widely-adopted alternative. – fra-san Aug 01 '20 at 15:24
  • well, this means that I must use a cron every 1 minute: to run an event_on_file.sh script; the idea that this script generates an event on the TXT files (if they exist), is not in real time but would work on demand for the existence of the txt files. –  Aug 01 '20 at 16:32
  • What I am not sure of; it is if doing it with a cron, then a .sh, that for example executes: mv filename.txt filename.txt generates a valid event for inotify. –  Aug 01 '20 at 16:35
  • what do you think? –  Aug 01 '20 at 16:36
  • @FranciscoNúñez mv filename.txt filename.txt will trigger events that inotify can monitor if, assuming you are copying from the curlftpfs file system, the target is on a "local" (e.g. ext4) file system. That said, comments aren't a good fit for this kind of discussion, I'd rather suggest you to ask a new question. – fra-san Aug 01 '20 at 19:32