Смотрите файловую систему в реальном времени на OS X и Ubuntu

11

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

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

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

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

Адриан Шнайдер
источник
1
Мне нравится fswatchOS X, который я нашел по вопросу, который был помечен как дубликат - superuser.com/questions/445907/…
cwd

Ответы:

11

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

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

pip install watchdog

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

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

команда-команда watchmedo \
    - рекурсивный \
    --command = ' echo "$ {watch_src_path}" ' \
     / some / folder

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

slhck
источник
Похоже, что действия с папками имеют некоторые ограничения (и их трудно протестировать без OSX), но они 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.

speedofmac
источник
Дали ему шанс, но немного трудно настроить без какого-либо рубинового фона. Спасибо, в любом случае!
Адриан Шнайдер
это круто. Любая идея, как сделать это рекурсивно смотреть папки ниже?
Нейт Флинк
Если меня не волнует выполнение команды на изменение, будет ли это мультиплатформенным или только Unix? И действительно ли это в реальном времени? Некоторые наблюдатели файлов имеют нелепую задержку (минуты).
Automatico
2

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

watch -n <s> lsof

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

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

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

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

DDay
источник
0

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

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

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

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

Кристиан Лонг
источник