Assista ao sistema de arquivos em tempo real no OS X e Ubuntu

11

Estou procurando uma ferramenta CLI que assista a um diretório e cuspa os nomes dos arquivos que mudam em tempo real.

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

Estou ciente de inotify( inotify-tools?) E parece ser o que preciso, mas preciso de algo que seja compatível com Linux (no meu caso, Ubuntu) e OSX.

Ele não precisa ser muito rápido, mas é necessário acionar alterações (dentro de um segundo é razoável). Além disso, não preciso necessariamente do programa CLI exato mencionado acima. Se alguma tecnologia subjacente existir e for facilmente programável em ambas as plataformas, isso também seria ótimo.

Adrian Schneider
fonte
1
Eu gosto fswatchdo OS X, que eu encontrei em uma pergunta que foi marcada como duplicada - superuser.com/questions/445907/…
cwd

Respostas:

11

O OS X normalmente usaria Ações de Pasta ou Iniciado para esta tarefa.

A única ferramenta de plataforma cruzada que conheço é a API de vigilância para Python (disponível para OS X e Linux). Instale-o através pip(ou easy_install)

pip install watchdog

Ele vem com a watchmedoferramenta de linha de comando, que permite executar comandos do shell nos eventos do sistema. Verifique sua sintaxe geral comwatchmedo --help

Aqui está um pequeno exemplo, onde você pode modificar facilmente o comando e o caminho destacado em negrito:

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

Isso simplesmente cuspiria os caminhos para todos os arquivos ou pastas alterados, permitindo que você canalize watchmedoa saída para outro comando do shell.

slhck
fonte
Parece que as Ações da Pasta têm algumas limitações (e são difíceis de testar sem o OSX), mas watchmedoestão funcionando perfeitamente para mim. Obrigado!
Adrian Schneider
2

Alterei alguns scripts Ruby que encontrei para fazer exatamente o que você está procurando. Aqui está o código 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

Chamei esse script de "OnSaveFolder.rb". São necessários dois parâmetros: a pasta que você deseja observar quanto a alterações e o código bash que você deseja executar quando houver uma alteração. Por exemplo,

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

Eu espero que isso ajude! Descobri que o ruby ​​funciona muito bem para esse tipo de coisa e está instalado no OS X por padrão.

speedofmac
fonte
Deu um tiro, mas um pouco difícil de ajustar sem qualquer fundo Ruby. Obrigado mesmo assim!
Adrian Schneider
isso é ótimo. alguma idéia de como fazê-lo assistir recursivamente as pastas abaixo?
Nate Flink
Se eu não me importo com a execução do comando na mudança, isso seria multiplataforma ou apenas unix? E é realmente em tempo real? Alguns observadores de arquivos por aí têm um atraso ridículo (minutos).
Automatico
2

Você pode colocar lsofum watchcomando e atualizá-lo a cada <s>segundo:

watch -n <s> lsof

e inicie isso com qualquer filtro, como assistir pid1, pid2, pid3 e ignorar pid4

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

Se isso não for suficiente, você sempre pode escrever seus próprios filtros com grep.

Para o OS X, consulte as respostas desta pergunta .

Dia D
fonte
0

entr é legal. Você pode filtrar os arquivos exatos que deseja assistir, assim.

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

Se você deseja monitorar apenas certos arquivos dentro de um diretório, você pode criar seu findcomando para que ele retorne apenas os arquivos que deseja assistir.

Acho mais fácil configurar do que fswatch.

Christian Long
fonte