Наблюдайте за файловой системой в реальном времени на OS X и Ubuntu

Наблюдайте за файловой системой в реальном времени на OS X и Ubuntu

Я ищу инструмент CLI, который будет следить за каталогом и выдавать имена файлов, которые изменяются в режиме реального времени.

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

Я знаю о inotify( inotify-tools?), и, похоже, это то, что мне нужно, но мне нужно что-то, совместимое как с Linux (в моем случае Ubuntu), так и с OSX.

Он не должен быть молниеносным, но он должен срабатывать при изменениях (в течение секунды — разумно). Кроме того, мне не обязательно нужна именно та программа CLI, о которой я говорил выше. Если бы существовала какая-то базовая технология, которую можно было бы легко заскриптовать на обеих платформах, это тоже было бы здорово.

решение1

OS X обычно используетДействия с папкамиилиЗапущендля этой задачи.

Единственный известный мне кроссплатформенный инструмент — этоAPI сторожевого таймерадля Python (доступно для OS X и Linux). Установите его через pip(или easy_install)

pip install watchdog

Он поставляется с watchmedoинструментом командной строки, который позволяет вам запускать команды оболочки для системных событий. Проверьте его общий синтаксис с помощьюwatchmedo --help

Вот короткий пример, в котором вы можете легко изменить команду и путь, выделенный жирным шрифтом:

watchmedo shell-команда \
    --рекурсивный \
    --команда='эхо "${watch_src_path}"' \
    /какая-то/папка

Это просто выведет пути ко всем измененным файлам или папкам, что позволит вам передать watchmedoвывод другой команде оболочки.

решение2

Я подправил несколько скриптов Ruby, которые мне попадались, чтобы они делали именно то, что вы ищете. Вот код 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

Я назвал этот скрипт "OnSaveFolder.rb". Он принимает два параметра: папку, за которой вы хотите следить на предмет изменений, и bash-код, который вы хотите запустить при возникновении изменений. Например,

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

Надеюсь, это поможет! Я обнаружил, что Ruby отлично подходит для таких задач, и он установлен в OS X по умолчанию.

решение3

Вы можете lsofввести watchкоманду и сделать так, чтобы она обновлялась каждую <s>секунду:

watch -n <s> lsof

и запустите его с любым фильтром, например, наблюдая за pid1, pid2, pid3 и игнорируя pid4

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

Если этого недостаточно, вы всегда можете написать свои собственные фильтры с помощью grep.

Для OS X см. этовопросответы.

решение4

вхэто хорошо. Вы можете отфильтровать точные файлы, которые хотите просматривать, вот так.

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

Если вы хотите, чтобы он отслеживал только определенные файлы внутри каталога, вы можете составить команду findтак, чтобы она возвращала только те файлы, за которыми вы хотите следить.

Мне его проще настроить, чем fswatch.

Связанный контент