Regarder le système de fichiers en temps réel sur OS X et Ubuntu

11

Je cherche un outil CLI qui surveillera un répertoire et crachera les noms des fichiers qui changent en temps réel.

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

Je connais inotify( inotify-tools?) Et cela semble être ce dont j'ai besoin, mais j'ai besoin de quelque chose qui soit à la fois compatible avec Linux (dans mon cas Ubuntu) et OSX.

Il n'a pas besoin d'être rapide comme l'éclair, mais il doit se déclencher lors des changements (dans une seconde, c'est raisonnable). De plus, je n'ai pas nécessairement besoin du programme CLI exact mentionné ci-dessus. Si une technologie sous-jacente existe et est facilement scriptable sur les deux plates-formes, ce serait génial aussi.

Adrian Schneider
la source
1
J'aime fswatchpour OS X que j'ai trouvé sur une question étiquetée comme doublon - superuser.com/questions/445907/…
cwd

Réponses:

11

OS X utilise généralement les actions de dossier ou Launchd pour cette tâche.

Le seul outil multiplateforme que je connaisse est l' API de surveillance pour Python (donc disponible pour OS X et Linux). Installez-le via pip(ou easy_install)

pip install watchdog

Il est livré avec l' watchmedooutil de ligne de commande, qui vous permet d'exécuter des commandes shell sur les événements système. Vérifiez sa syntaxe générale avecwatchmedo --help

Voici un court exemple, où vous pouvez facilement modifier la commande et le chemin mis en évidence en gras:

watchmedo shell-command \
    --récursif \
    --command = ' echo "$ {watch_src_path}" ' \
     / certains / dossier

Cela cracherait simplement les chemins vers tous les fichiers ou dossiers modifiés, vous permettant de diriger watchmedola sortie de vers une autre commande shell.

slhck
la source
Il semble que les actions sur les dossiers aient certaines limites (et sont difficiles à tester sans OSX), mais cela watchmedofonctionne parfaitement pour moi. Merci!
Adrian Schneider
2

J'ai modifié quelques scripts Ruby que j'ai rencontrés pour faire exactement ce que vous cherchez. Voici le code Ruby:

#!/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

J'ai nommé ce script "OnSaveFolder.rb". Il prend deux paramètres: le dossier que vous souhaitez surveiller pour les modifications et le code bash que vous souhaitez exécuter en cas de modification. Par exemple,

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

J'espère que ça aide! J'ai trouvé que ruby ​​fonctionne très bien pour ce type de chose, et il est installé sur OS X par défaut.

speedofmac
la source
Je lui ai donné un coup mais un peu difficile à modifier sans arrière-plan Ruby. Merci quand même!
Adrian Schneider
c'est bien. une idée comment faire pour regarder récursivement les dossiers ci-dessous?
Nate Flink
Si je ne me soucie pas de l'exécution de la commande lors d'un changement, est-ce que ce serait multi-plateforme, ou seulement Unix? Et est-ce réellement le temps réel? Certains observateurs de fichiers ont un délai ridicule (minutes).
Automatico
2

Vous pouvez mettre lsofune watchcommande et la mettre à jour toutes les <s>secondes:

watch -n <s> lsof

et lancez-le avec n'importe quel filtre, comme regarder pid1, pid2, pid3 et ignorer pid4

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

Si cela ne suffit pas, vous pouvez toujours écrire vos propres filtres avec grep.

Pour OS X, voir les réponses à cette question .

DDay
la source
0

entr est sympa. Vous pouvez filtrer les fichiers exacts que vous souhaitez qu'il regarde, comme ceci.

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

Si vous souhaitez qu'il ne surveille que certains fichiers dans un répertoire, vous pouvez créer votre findcommande afin qu'elle ne renvoie que les fichiers que vous souhaitez regarder.

Je trouve cela plus facile à configurer que fswatch.

Christian Long
la source