3 # This script watches modifications on the given directory, using the new # FSEvents API in Leopard.
5 require 'osx/foundation'
6 OSX.require_framework '/System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework'
12 $COMMAND = File.basename($0)
13 $USAGE = "Usage: #{$COMMAND} [OPTIONS] <command> [<args> ...]"
15 options = OpenStruct.new
16 options.directoriesOnly = false
17 options.outputFile = "-"
19 opts = OptionParser.new do |opts|
22 opts.separator "Specific options:"
24 opts.on("-d", "--dir-only", "Only display directories") do
25 options.directoriesOnly = true
28 opts.on("-o", "--output FILE", "Write output to a file") do |fileName|
29 options.outputFile = fileName
32 opts.on_tail("-h", "--help", "Show this message") do
44 if options.outputFile == "-"
45 outputHandle = $stdout.clone
47 outputHandle = File.open(options.outputFile, "w")
52 startId = FSEventsGetCurrentEventId()
53 # Used to compare with mtime, which only has second accuracy
54 startTime = Time.now.to_i
59 rescue SystemCallError => e
71 fsevents_cb = proc do |stream, ctx, numEvents, paths, marks, eventIDs|
73 numEvents.times do |n|
74 allPaths.add(paths[n])
78 stream = FSEventStreamCreate(
85 KFSEventStreamCreateFlagNoDefer)
87 die "Failed to create the FSEventStream" unless stream
89 FSEventStreamScheduleWithRunLoop(
91 CFRunLoopGetCurrent(),
92 KCFRunLoopDefaultMode)
94 ok = FSEventStreamStart(stream)
95 die "Failed to start the FSEventStream" unless ok
98 FSEventStreamFlushSync(stream)
99 allPaths.sort.each do |path|
100 if File.exists?(path)
101 outputHandle.puts path
102 if (!options.directoriesOnly)
103 Dir.foreach(path) do |file|
104 fullPath = File.join(path, file)
105 stat = File.stat(fullPath)
106 if (stat.mtime.to_i >= startTime)
107 outputHandle.puts " #{file}"
112 outputHandle.puts "#{path} !"
116 FSEventStreamStop(stream)
117 FSEventStreamInvalidate(stream)
118 FSEventStreamRelease(stream)