eonist / FileWatcher

Monitoring file system changes in macOS
MIT License
206 stars 13 forks source link

Deleting files show as "renamed" instead of "removed" #16

Open njmullen opened 4 years ago

njmullen commented 4 years ago

After importing the project and getting it setup, I tested deleting files from a directory. The notifications fire properly but they state that the file was renamed instead of removed. Additionally, adding a file will say that it was modified instead of created.

I tried this on an iCloud and a non-iCloud Drive folder.

This is the output of printing from extension FileWatcherEvent

Swift.print(self.removed) Swift.print(self.renamed) Swift.print(result.description)

false true The file /Users/nick/Downloads/IMG_1739.jpeg was renamed

Any ideas? Love the library btw, thank you!

eonist commented 4 years ago

Hey there. Love that you tried the framework.

Have your tried:

filewatcher.callback = { event in
  print(event.created) // both file and folder
  print(event.fileCreated)
  print(event.folderCreated)
  print("Something happened here: " + event.path)
}

can be found here: https://github.com/eonist/FileWatcher/blob/e9e1e140cacd39abf92ef35fc20d17ccc2cde96b/FileWatcherEvent.swift#L27

and

https://github.com/eonist/FileWatcher/blob/e9e1e140cacd39abf92ef35fc20d17ccc2cde96b/FileWatcherEvent.swift#L40

njmullen commented 4 years ago

Here is my AppDelegate.swift didFinishLaunching method

` func applicationDidFinishLaunching(_ aNotification: Notification) { print("Initializing application") let filewatcher = FileWatcher([NSString(string: "~/Downloads").expandingTildeInPath])

    filewatcher.callback = { event in
        print("Something happened here: " + event.path)
        print(event.fileRemoved)
        print(event.dirRemoved)
        print(event.fileCreated)
        print(event.dirCreated)
        print(event.flags)
        print(event)
        print(event.description)
    }

    filewatcher.start() // start monitoring
    filewatcher.queue = DispatchQueue.global()

`

and here is my output for deleting then un-deleting a file

Something happened here: /Users/nick/Downloads/IMG_1738.jpeg false false false false 67584 filelock.FileWatcherEvent The file /Users/nick/Downloads/IMG_1738.jpeg was renamed Something happened here: /Users/nick/Downloads/.DS_Store false false false false 70656 filelock.FileWatcherEvent The file /Users/nick/Downloads/.DS_Store was modified Something happened here: /Users/nick/Downloads/IMG_1738.jpeg false false false false 67584 filelock.FileWatcherEvent The file /Users/nick/Downloads/IMG_1738.jpeg was renamed Something happened here: /Users/nick/Downloads/.DS_Store false false false false 70656 filelock.FileWatcherEvent The file /Users/nick/Downloads/.DS_Store was modified

eonist commented 4 years ago

Apple changes how their os works from time to time. If you delete a file and it goes to the trash its now recorded as a rename. If you skip the trash bin (aka immediate deletion), its recorded as delete. I update the framework to differentiate the two. Its not perfect but, a temp solution. I think its possible to fix by working a bit on the FSEvent flags. You can do additional testing with a file assertion method. With something like: renamed && !FileManager.assertExistence(filePath)

alioguzhan commented 4 years ago

Hey, with the latest update you sent, I am sending a new version 0.2.1 to the Cocoa Pods. Sounds good? @eonist

eonist commented 4 years ago

@alioguzhan do I need to push git tags?

alioguzhan commented 4 years ago

@eonist Oh, It would be great. we need 0.2.1 tag

eonist commented 4 years ago

@alioguzhan I'm at work so I just did it with github, should work the same as using gif in terminal right?: https://github.com/eonist/FileWatcher/releases/tag/0.2.1

alioguzhan commented 4 years ago

@eonist Yes it is correct. I can take it from here. I will release a new version to CocoaPods. Thanks

alioguzhan commented 4 years ago

It's done : https://cocoapods.org/pods/FileWatcher @njmullen @eonist

njmullen commented 4 years ago

Awesome, thank you so much!

Has this change been pushed to the repo yet? I tried replacing FIleWatcherEvent.swift with the one from the latest commit 2 days ago, but I'm still having the same issue. I'm using it just with the files rather than through Cocoapods.

eonist commented 4 years ago

Did you try doing alt + cmd + del on a file? Does this produce a delete flag?

kamleshgk commented 3 years ago

@eonist I tried your cool solution and i'm able a) to monitor multiple directories b) Used background thread and NSOperations. Works fine c) Changes in subdirectories are also detected. Huge.

Fantastic work. But when i add or removed a file - the status shows is 'Rename'

In below code - fileCreated and fileCreated is never 'true' fileRenamed is true in both cases - adding and removing

Any way to distinguish between addition and removal?

if event.fileCreated == true { Swift.print("New File is created here... \(event.path)") } if event.fileRemoved == true { Swift.print("New File is removed from here... \(event.path)") } if event.fileRenamed == true { Swift.print("New File is renamed from here... \(event.path)") }

eonist commented 3 years ago

In apples doc it says:

/*
 * A file system object was removed at the specific path supplied in this event.
 * (This flag is only ever set if you specified the FileEvents flag when creating the stream.)
 */
@available(OSX 10.7, *)
public var kFSEventStreamEventFlagItemRemoved: Int { get }

This flag is only ever set if you specified the FileEvents flag when creating the stream I don't understand what that means and 10min research on google doesn't bring immediate clarification. But if you want to differentiate removal and renaming. you can simply do: if !FileManager().fileExists(atPath: event.path) { Swift.print("was deleted") }

I added this in the latest commit.

kamleshgk commented 3 years ago

Hey @eonist I totally appreciate the reply. I just do a file exists as you suggested and if it does not exist, its removed.

Cheers!

alienator88 commented 7 months ago

Ran into this issue as well but it was difficult to check if an item was in the trash with .fileExists since it's a system directory and needed full disk permission for some reason, at least in my case. If anybody runs into this, I was able to check if the file is in the trash with getRelationship. Here's an extension, can be adapted to other directories too:

extension FileManager {
    public func isInTrash(_ file: URL) -> Bool {
        var relationship: URLRelationship = .other
        try? getRelationship(&relationship, of: .trashDirectory, in: .userDomainMask, toItemAt: file)
        return relationship == .contains
    }
}

Usage:

let fileExistsInTrash = FileManager.default.isInTrash(file)

Also @eonist, much appreciation for the package!

eonist commented 7 months ago

Haa! Nice method! And nice way of solving something adhock! FileObservability is definitely a bit of dark magic to cover all needs.