Я ищу инструмент 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
.