Beobachten Sie das Dateisystem in Echtzeit unter OS X und Ubuntu

11

Ich suche ein CLI-Tool, das ein Verzeichnis überwacht und die Namen von Dateien ausspuckt, die sich in Echtzeit ändern.

some_watch_command /path/to/some/folder | xargs some_callback

Ich bin mir bewusst inotify( inotify-tools?) Und es scheint das zu sein, was ich brauche, aber ich brauche etwas, das sowohl Linux (in meinem Fall Ubuntu) als auch OSX kompatibel ist.

Es muss nicht blitzschnell sein, aber es muss bei Änderungen ausgelöst werden (innerhalb einer Sekunde ist vernünftig). Außerdem brauche ich nicht unbedingt das oben erwähnte genaue CLI-Programm. Wenn eine zugrunde liegende Technologie vorhanden ist und auf beiden Plattformen leicht skriptfähig ist, wäre das auch großartig.

Adrian Schneider
quelle
1
Ich mag fswatchfür OS X , die ich auf eine Frage gefunden, die als Duplikat markiert wurde - superuser.com/questions/445907/...
cwd

Antworten:

11

OS X verwendet normalerweise Ordneraktionen oder Launchd für diese Aufgabe.

Das einzige plattformübergreifende Tool, das ich kenne, ist die Watchdog-API für Python (daher für OS X und Linux verfügbar). Installieren Sie es durch pip(oder easy_install)

pip install watchdog

Es wird mit dem watchmedoBefehlszeilentool geliefert, mit dem Sie Shell-Befehle für Systemereignisse ausführen können. Überprüfen Sie die allgemeine Syntax mitwatchmedo --help

Hier ist ein kurzes Beispiel, in dem Sie den Befehl und den fett hervorgehobenen Pfad leicht ändern können:

watchmedo shell-command \
    --rekursiv \
    --command = ' echo "$ {watch_src_path}" ' \
     / some / folder

Dies würde einfach die Pfade zu allen geänderten Dateien oder Ordnern ausspucken, sodass Sie die watchmedoAusgabe an einen anderen Shell-Befehl weiterleiten können.

slhck
quelle
Es sieht so aus, als hätten Ordneraktionen einige Einschränkungen (und sind ohne OSX schwer zu testen), watchmedofunktionieren aber perfekt für mich. Vielen Dank!
Adrian Schneider
2

Ich habe einige Ruby-Skripte optimiert, um genau das zu tun, wonach Sie suchen. Hier ist der Ruby-Code:

#!/usr/bin/ruby
# Inspired by http://vikhyat.net/code/snippets/#watchfile

# How to use:
# This script takes two paramaters:  a folder and a shell command
# The script watches for when files in the folder are changed.  When they are, the shell command executes
# Here are some shortcuts you can put in the shell script:
# %F = filename (with extension)
# %B = base filename (without extension)


unless ARGV.length == 2
  puts "\e[32m    Usage: \e[0mruby OnSaveFolder.rb 'folder' 'command'"
  exit
end

require 'digest/md5'
require 'ftools'

$md5 = ''
$directory = File.expand_path(ARGV[0])
$contents = `ls #{$directory}`
$contentsList = $contents.split("\n")
$fileList = []


Dir.chdir($directory)

for i in $contentsList
  if ( File.file?(File.expand_path(i)) == true)
    $fileList.push(i)
  end
end

$processes = []

def watch(file, timeout, &cb)
  $md5 = Digest::MD5.hexdigest(File.read(file))
  loop do
    sleep timeout
    if ( temp = Digest::MD5.hexdigest(File.read(file)) ) != $md5
      $md5 = temp
      cb.call(file)
    end
  end
end

puts "\e[31m Watching files in folder \e[34m #{$directory}"
puts "\e[32m    Press Control+C to stop \e[0m"

for i in $fileList
  pid = fork do
    $num = 0
    $filePath = File.expand_path(i)

    watch i, 1 do |file|
      puts "\n     #{i} saved"

      $command = ARGV[1].dup
      if ( ARGV[1].include?('%F') )
        $command = $command.gsub!('%F', i)
      end
      if ( ARGV[1].include?('%B') )
        $command = $command.gsub!('%B', File.basename(i, '.*'))
      end

      $output = `#{$command}`
      if ( $output != '')
        puts "\e[34m     #{$command}\e[31m output: \e[0m"
        puts $output
      end
      puts "\e[34m     #{$command}\e[31m finished \e[0m (#{$num}, #{Time.now})\n"
      $num += 1

    end
  end
  $processes.push(pid)
end

Process.wait(pid)

for i in $processes
  `kill #{i}`
end

Ich habe dieses Skript "OnSaveFolder.rb" genannt. Es werden zwei Parameter benötigt: der Ordner, den Sie auf Änderungen überwachen möchten, und der Bash-Code, den Sie ausführen möchten, wenn Änderungen vorgenommen wurden. Zum Beispiel,

ruby OnSaveFolder.rb '/home/Movies' 'echo "A movie has been changed!"'

Ich hoffe das hilft! Ich habe festgestellt, dass Ruby für diese Art von Dingen sehr gut funktioniert und standardmäßig unter OS X installiert ist.

speedofmac
quelle
Hat es versucht, aber ohne Ruby-Hintergrund ein wenig schwer zu optimieren. Danke trotzdem!
Adrian Schneider
das ist toll. Haben Sie eine Idee, wie Sie die folgenden Ordner rekursiv anzeigen können?
Nate Flink
Wenn mir die Ausführung des Befehls bei Änderung nicht wichtig ist, wäre dies dann plattformübergreifend oder nur Unix? Und ist es tatsächlich Echtzeit? Einige Datei-Beobachter haben eine lächerliche Verzögerung (Minuten).
Automatico
2

Sie können lsofeinen watchBefehl eingeben und alle <s>Sekunden aktualisieren lassen :

watch -n <s> lsof

und starten Sie dies mit einem beliebigen Filter, z. B. pid1, pid2, pid3 beobachten und pid4 ignorieren

lsof -p "pid1,pid2,pid3,^pid4"

Wenn das nicht genug ist, können Sie jederzeit Ihre eigenen Filter mit grep schreiben.

Informationen zu OS X finden Sie in den Antworten dieser Frage .

DDay
quelle
0

Entr ist nett. Sie können genau die Dateien filtern, die Sie sehen möchten.

find . -name '*.py' | entr python runTests.py

Wenn Sie möchten, dass nur bestimmte Dateien in einem Verzeichnis überwacht werden, können Sie Ihren findBefehl so gestalten, dass nur die Dateien zurückgegeben werden, die Sie anzeigen möchten.

Ich finde es einfacher zu konfigurieren als fswatch.

Christian Long
quelle