emcrisostomo / fswatch

A cross-platform file change monitor with multiple backends: Apple OS X File System Events, *BSD kqueue, Solaris/Illumos File Events Notification, Linux inotify, Microsoft Windows and a stat()-based backend.
https://emcrisostomo.github.io/fswatch/
GNU General Public License v3.0
4.96k stars 327 forks source link

fswatch command fires multiple events for a single move operation #312

Open unlocked2412 opened 1 year ago

unlocked2412 commented 1 year ago

Hello, and thank you for this amazing tool

I have a photos.sh file (osascript set to JavaScript):

#!/usr/bin/osascript -l JavaScript

function run(argv) {
    return importFileIntoPhotos(argv[0])
};

// importFileIntoPhotos :: FilePath -> IO ()
const importFileIntoPhotos = fp => {
    const 
        appPhotos = Application("Photos");
    return appPhotos.import([Path(fp)])
};

and, the following test.sh file:

#!/bin/zsh

fp="$HOME/Documents/Samsung T5"

fpScript="$HOME/Library/CloudStorage/Dropbox/VSC Files/Automation/Manuel/photos.sh"

fswatch -0 -event-flags -r --exclude=".*\.DS_Store" "$fp" | xargs -0 -n1 -r -I {} "$fpScript" "{}"

I execute test.sh in Terminal. With that process open, whenever I move a single photo into fp folder, the same photo is imported multiple times into ​Photos​ app. Then, I have to kill the process.

Do you know how can I fix this issue, and import a single photo corresponding to a single move operation ? Is there something wrong with my code ?

Specs:

MacBook Air M1 with macOS Ventura

unlocked2412 commented 1 year ago

UPDATE:

Upon further testing, I have more clarity about the issue. Whenever the file is imported into Photos, a new event is sent (and captured) by fswatch, so it gets triggered again.

unlocked2412 commented 1 year ago

Now, the act of importing into Photos doesn't trigger an event that could be captured by fswatch, and also doesn't trigger duplicated events. Not sure what happened. I am closing this issue.

unlocked2412 commented 1 year ago

I am reopening the issue because the problem persists. I tried with Preview app, and I get duplicated events again.

tgill880 commented 5 months ago

I have encountered something similar. Here is what I found.

System: MacBook Air M1, Sonoma 14.2.1 fswatch --version: fswatch 1.17.1

We want a file path whenever a file is created in the watch folder.

Here is a dirt simple script that shows we are getting the file paths we want.

#! /bin/zsh

FOLDER=$1
echo "monitoring $FOLDER"

# Using fswatch to monitor the folder for changes.
fswatch "$FOLDER" | while read FILE
do
  echo "file: $FILE"
done

Execute the script.

./watch.sh watch_folder

In another terminal, drop some files, delete them, create and remove a directory.

cp test.png watch_folder
cp test.png watch_folder/test2.png
rm watch_folder/*
mkdir watch_folder/test
rmdir watch_folder/test

Output

monitoring watch_folder
file: /Users/Joe/Projects/LATscan/watch_folder/test.png
file: /Users/Joe/Projects/LATscan/watch_folder/test2.png
file: /Users/Joe/Projects/LATscan/watch_folder/test.png
file: /Users/Joe/Projects/LATscan/watch_folder/test2.png
file: /Users/Joe/Projects/LATscan/watch_folder/test
file: /Users/Joe/Projects/LATscan/watch_folder/test

Good news! We are getting the file paths we want. The other paths (from removing files, directory stuff) can be filtered out with an event mask and/or filtering.

Now let's open these image files with the default application (Preview). Add this line below the echo command in the loop. open "$FILE" &

Copy one file into our watch_folder.

 $ ./watch.sh watch_folder
monitoring watch_folder
file: /Users/Joe/Projects/LATscan/watch_folder/test.png
file: /Users/Joe/Projects/LATscan/watch_folder/test.png
file: /Users/Joe/Projects/LATscan/watch_folder/test.png
file: /Users/Joe/Projects/LATscan/watch_folder/test.png
file: /Users/Joe/Projects/LATscan/watch_folder/test.png
file: /Users/Joe/Projects/LATscan/watch_folder/test.png
file: /Users/Joe/Projects/LATscan/watch_folder/test.png
file: /Users/Joe/Projects/LATscan/watch_folder/test.png
^C

Boom. Although only one image is opened by Preview, the script loops until we abort it (similar to the OP). I tried various combinations of the open command, and substituted ImageJ.app, with the same results. open -a ImageJ.app "$FILE" &

What DOES work is viewing the image with the ImageMagick display command. Replace the open line with this: magick "$FILE" - | display - & Now multiple images display in an XQuartz (X11) window, without the runaway loop.

NOTE: To use display, download the macOS binaries from ImageMagick.org, and don't use the version installed with brew. Also, install XQuartz if it's not on your system.

For the next tests, I just looked at the raw fswatch output to stdout with different monitors.

For the queue_monitor, the file paths were outputted without the file name.

$ fswatch -m queue_monitor watch_folder
/Users/Joe/Projects/LATscan/watch_folder
/Users/Joe/Projects/LATscan/watch_folder
/Users/Joe/Projects/LATscan/watch_folder

For the poll_monitor, no output at stdout.

$ fswatch -m poll_monitor
[no output]

Summary