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
5.04k stars 328 forks source link

Regex end of string anchor is not respected #240

Open Ductapemaster opened 4 years ago

Ductapemaster commented 4 years ago

I've noticed that in one specific case, the regex end of string anchor $ is not being respected when using the -i command. Here is some test code:

fswatch -i "\.txt$" --event="Created" ~/Downloads/ | tee >(xargs -I {} cp {} {}.log)

When you create a new .txt file in the watched directory, the command will copy it appending .log to the end. This, however, still triggers the regex! It results in the command being run over and over again, creating copies of the last file created.

Example output:

$ fswatch -i "\.txt$" --event="Created" ~/Downloads/ | tee >(xargs -I {} cp {} {}.log)
~/Downloads/test.txt
~/Downloads/test.txt.log
~/Downloads/test.txt.log.log
~/Downloads/test.txt.log.log.log
~/Downloads/test.txt.log.log.log.log
~/Downloads/test.txt.log.log.log.log.log
~/Downloads/test.txt.log.log.log.log.log.log
~/Downloads/test.txt.log.log.log.log.log.log.log
~/Downloads/test.txt.log.log.log.log.log.log.log.log

Any ideas about what is going on here? I will work around this in my app because I know both extensions and can ignore the new one, but it seems as if the regex behavior is not as intended or described.

direvus commented 2 years ago

The regexp is fine, but you have to add -e '.*' to your fswatch command to get it to exclude everything else.

The filtering behaviour in fswatch is a little ... idiosyncratic. It matches everything unless you explicitly exclude it, even if you give a -i include pattern. So an -i on its own without an -e is totally useless. Other things to watch out for; the order of -i and -e arguments doesn't matter, an -i match always trumps an -e match, and the default regexp engine is very basic. If you want to do anything more fancy than ^, *, $ you pretty much have to switch on the "extended" regexp option with -E.