Tonton Filesystem secara Real Time di OS X dan Ubuntu

11

Saya mencari alat CLI yang akan menonton direktori dan memuntahkan nama-nama file yang berubah secara real time.

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

Saya menyadari inotify( inotify-tools?) Dan sepertinya itu yang saya butuhkan, tapi saya butuh sesuatu yang Linux (dalam kasus saya Ubuntu) dan kompatibel dengan OSX.

Tidak perlu kilat cepat, tetapi perlu memicu perubahan (dalam hitungan detik masuk akal). Juga, saya tidak perlu program CLI persis seperti yang disebutkan di atas. Jika beberapa teknologi yang mendasarinya ada dan mudah skrip di kedua platform itu akan menjadi besar juga.

Adrian Schneider
sumber
1
Saya suka fswatchuntuk OS X yang saya temukan pada pertanyaan yang ditandai sebagai duplikat - superuser.com/questions/445907/…
cwd

Jawaban:

11

OS X biasanya akan menggunakan Tindakan Folder atau Launchd untuk tugas ini.

Satu-satunya alat lintas-platform yang saya tahu adalah API pengawas untuk Python (dengan demikian tersedia untuk OS X dan Linux). Instal melalui pip(atau easy_install)

pip install watchdog

Itu datang dengan watchmedoalat baris perintah, yang memungkinkan Anda untuk menjalankan perintah shell pada peristiwa sistem. Periksa sintaks umumnya denganwatchmedo --help

Berikut adalah contoh singkat, di mana Anda dapat dengan mudah mengubah perintah dan jalur yang disorot dengan huruf tebal:

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

Ini hanya akan memuntahkan path ke semua file atau folder yang diubah, memungkinkan Anda untuk mem watchmedo- pipe output ke perintah shell lain.

slhck
sumber
Sepertinya Tindakan Folder memiliki beberapa keterbatasan (dan sulit untuk diuji tanpa OSX), tetapi watchmedoberfungsi dengan baik untuk saya. Terima kasih!
Adrian Schneider
2

Saya telah men-tweak beberapa skrip Ruby yang saya temui untuk melakukan apa yang Anda cari. Inilah kode 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

Saya menamai skrip ini "OnSaveFolder.rb". Dibutuhkan dua parameter: folder yang ingin Anda perhatikan perubahannya, dan kode bash yang ingin Anda jalankan ketika ada perubahan. Sebagai contoh,

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

Saya harap ini membantu! Saya telah menemukan bahwa ruby ​​bekerja sangat baik untuk jenis hal ini, dan itu diinstal pada OS X secara default.

speedofmac
sumber
Memberi suntikan tetapi sedikit sulit untuk mengubah tanpa latar belakang Ruby. Bagaimanapun, terima kasih!
Adrian Schneider
ini bagus. ada ide bagaimana membuatnya menonton folder secara rekursif di bawah?
Nate Flink
Jika saya tidak peduli dengan eksekusi perintah pada perubahan, apakah ini multi-platform, atau hanya unix? Dan apakah itu sebenarnya waktu nyata? Beberapa pengamat file di luar sana memiliki keterlambatan konyol (menit).
Otomatis
2

Anda bisa memasukkan lsofke dalam watchperintah dan memilikinya update setiap <s>detik:

watch -n <s> lsof

dan luncurkan itu dengan filter apa pun, seperti menonton pid1, pid2, pid3 dan mengabaikan pid4

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

Jika itu tidak cukup, Anda selalu bisa menulis filter sendiri dengan grep.

Untuk OS X, lihat jawaban pertanyaan ini .

Hari H
sumber
0

entr itu bagus. Anda dapat memfilter file persis yang Anda ingin tonton, seperti ini.

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

Jika Anda ingin hanya memonitor file tertentu di dalam direktori, Anda bisa membuat findperintah sehingga hanya mengembalikan file yang ingin Anda tonton.

Saya merasa lebih mudah untuk mengkonfigurasi daripada fswatch.

Christian Long
sumber