11

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

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

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

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

4 ответа4

11

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

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

pip install watchdog

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

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

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

Это просто высветит пути ко всем измененным файлам или папкам, что позволит вам направить вывод 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.

2

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

watch -n <s> lsof

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

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

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

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

0

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

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

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

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .