Смотреть файловую систему в режиме реального времени на OS X и Ubuntu
Я ищу инструмент CLI, который будет смотреть каталог и выкладывать имена файлов, которые изменяются в режиме реального времени.
some_watch_command /path/to/some/folder | xargs some_callback
Я в курсе inotify
(inotify-tools
?) и, кажется, это то, что мне нужно, но мне нужно что-то совместимое с Linux (в моем случае Ubuntu) и OSX.
Он не должен быть молниеносным, но должен вызывать изменения (в течение секунды это разумно). Кроме того, мне не обязательно нужна точная программа CLI, упомянутая выше. Если какая-то базовая технология существует и ее легко можно написать на обеих платформах, это тоже было бы здорово.
4 ответа
OS X обычно использует действия с папками или Launchd для этой задачи.
Единственный известный мне кроссплатформенный инструмент - это сторожевой API для Python (таким образом, доступный для OS X и Linux). Установите его через pip
(или же easy_install
)
pip install watchdog
Это идет с watchmedo
инструмент командной строки, который позволяет запускать команды оболочки для системных событий. Проверьте его общий синтаксис с watchmedo --help
Вот краткий пример, где вы можете легко изменить команду и путь, выделенный жирным шрифтом:
команда-команда watchmedo \ - рекурсивный \ --command = 'echo "$ {watch_src_path}"' \ / некоторые / папки
Это просто выложит пути ко всем измененным файлам или папкам, что позволит вам watchmedo
вывод в другую команду оболочки.
Вы могли бы поставить lsof
в watch
команда и обновить его каждый <s>
секунды:
watch -n <s> lsof
и запустить его с любым фильтром, таким как просмотр pid1, pid2, pid3 и игнорирование pid4
lsof -p "pid1,pid2,pid3,^pid4"
Если этого недостаточно, вы всегда можете написать свои собственные фильтры с помощью grep.
Для OS X посмотрите ответы на этот вопрос.
Я настроил несколько скриптов на 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.
Entr это хорошо. Вы можете отфильтровать файлы, которые хотите посмотреть, вот так.
find . -name '*.py' | entr python runTests.py
Если вы хотите, чтобы он отслеживал только определенные файлы в каталоге, вы можете создать свой find
команда, чтобы он возвращал только те файлы, которые вы хотите посмотреть.
Мне проще настроить, чем fswatch
,