Mac'te "watch" veya "inotifywait" gibi bir komut var mı?


287

Benim Mac (Snow Leopard) bir klasör izlemek ve sonra (sadece bir klasöre taşındı ne dosya adı vererek bir komut dosyası yürütmek istiyorum (parametre olarak ... x.sh "dosya adı")).

Tüm giriş 1 $ bazı dosyaları ve diğer şeyler hareket edecek bash (x.sh) yazılı bir komut dosyası var Sadece yeni dosyalar / klasörler bir dizine taşındığında / oluşturulduğunda bana dosya adını vermek için OSX gerekir.

Böyle bir komut var mı?


1
Muhtemelen mevcut tüm seçenekleri denediklerinden, DropBox'ın nasıl yaptığını sormalısınız.
Jeff Burdges

2
@JeffBurdges Kolay bir girişim olacağından pek emin değilim. Ancak Apple'ın FSEvents Referansını gözden geçirdikten sonra Dropbox bunu kullanmasaydı gerçekten aptalca olacağını söyleyebilirim . fswatchBir cevap aşağıda gerçeği kullanımda bu yöntem olduğu gibi util sundu.
Steven Lu

Yanıtlar:


447

fswatch

fswatch , bir dizini izlemek için Mac OS X FSEvents API'sini kullanan küçük bir programdır. Bu dizindeki herhangi bir değişiklikle ilgili bir olay alındığında, belirtilen shell komutu/bin/bash

GNU / Linux kullanıyorsanız, inotifywatch ( inotify-toolsçoğu dağıtımda paketin bir parçası ) benzer işlevler sağlar.

Güncelleme: fswatch artık BSD, Debian ve Windows dahil birçok platformda kullanılabilir.

Sözdizimi / Basit Bir Örnek

Birden çok yolu izleyebilmenin yeni yolu - sürüm 1.x ve üstü için :

fswatch -o ~/path/to/watch | xargs -n1 -I{} ~/script/to/run/when/files/change.sh

Not: tarafından verilen sayı -o, için xargsdeğilse komutun sonuna eklenir -I{}. Bu numarayı kullanmayı seçerseniz {}, komutunuzun herhangi bir yerine yerleştirin .

Sürüm 0.x için eski yol :

fswatch ~/path/to/watch ~/script/to/run/when/files/change.sh

Homebrew ile kurulum

12.09.2013 tarihinden itibaren homebrew - yay! Formül listenizi ( brew update) güncelleyin ve yapmanız gereken tek şey:

brew install fswatch

Homebrew olmadan kurulum

Bu komutları yazın Terminal.app

cd /tmp
git clone https://github.com/alandipert/fswatch
cd fswatch/
make
cp fswatch /usr/local/bin/fswatch

cSisteminizde bir derleyici yoksa, her ikisi de ücretsiz olan Xcode veya Xcode komut satırı araçlarını yüklemeniz gerekebilir. Ancak, durum buysa, muhtemelen sadece homebrew'a bakmalısınız .

fswatch1.x sürümü için ek seçenekler

Usage:
fswatch [OPTION] ... path ...

Options:
 -0, --print0          Use the ASCII NUL character (0) as line separator.
 -1, --one-event       Exit fsw after the first set of events is received.
 -e, --exclude=REGEX   Exclude paths matching REGEX.
 -E, --extended        Use exended regular expressions.
 -f, --format-time     Print the event time using the specified format.
 -h, --help            Show this message.
 -i, --insensitive     Use case insensitive regular expressions.
 -k, --kqueue          Use the kqueue monitor.
 -l, --latency=DOUBLE  Set the latency.
 -L, --follow-links    Follow symbolic links.
 -n, --numeric         Print a numeric event mask.
 -o, --one-per-batch   Print a single message with the number of change events.
                       in the current batch.
 -p, --poll            Use the poll monitor.
 -r, --recursive       Recurse subdirectories.
 -t, --timestamp       Print the event timestamp.
 -u, --utc-time        Print the event time as UTC time.
 -v, --verbose         Print verbose output.
 -x, --event-flags     Print the event flags.

See the man page for more information.

Talimatlarınız veya homebrew olmadan kurulum artık işe yaramıyor gibi görünüyor. makebir makefile bulamama konusunda hata verir. Neyse ki, fswatch şimdi MacPorts'ta, bu yüzden sudo port install fswatchçalışıyor, Homebrew yerine MacPorts kullananlarımız için çalışıyor.
coredumperror

Statik bağımsız değişkenlerle bir komut kullanıyorsanız (örneğin, birim testlerimi src ve test değişiklikleri üzerinde çalıştırıyordum) bu sizin için çalışmayabilir. Bu soru ( stackoverflow.com/questions/25689589/… ) ihtiyacım olan ikinci parçaydı.
jskulski

5
Seni orada duyuyorum:fswatch ./ | xargs -I{} cp {} ~/Dropbox/backup/latest/
fionbio

fswatch, .git dizini ile uğraşırken bazı hataları olan entr veya when_changed gibi araçlardan daha iyidir. fswatch çok daha profesyonel. Basitçe, fswatch .mevcut dizini izleyeceksiniz.
anonim

Ben öneririm fswatch -0 -v -o /path/to/watched/files | xargs -0 -n 1 -I {} [your command]ile -0boş değerlere için. Bu benim için daha az derleme için çalışıyor
boldnik

95

Bu amaçla launchd kullanabilirsiniz . Launchd, bir dosya yolu değiştirildiğinde otomatik olarak bir programı başlatacak şekilde yapılandırılabilir.

Örneğin, /usr/bin/loggerkullanıcı hesabımın masaüstü klasörü değiştirildiğinde aşağıdaki launchd config plist programı başlatır:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>logger</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/logger</string>
        <string>path modified</string>
    </array>
    <key>WatchPaths</key>
    <array>
        <string>/Users/sakra/Desktop/</string>
    </array>
</dict>
</plist>

Config plist'i etkinleştirmek için onu Kütüphane klasörünüzdeki LaunchAgents klasörüne "logger.plist" olarak kaydedin.

launchctlKabuktan sonra logger.plist komutunu aşağıdaki komutu çalıştırarak etkinleştirebilirsiniz:

$ launchctl load ~/Library/LaunchAgents/logger.plist

Masaüstü klasörü şimdi izleniyor. Her değiştirildiğinde, system.log dosyasında bir çıktı görmelisiniz (Console.app kullanın). Logger.plist'i devre dışı bırakmak için şunu çalıştırın:

$ launchctl unload ~/Library/LaunchAgents/logger.plist

Yukarıdaki yapılandırma dosyası WatchPathsseçeneği kullanır . Alternatif olarak QueueDirectoriesseçeneği de kullanabilirsiniz . Daha fazla bilgi için fırlatma kılavuzu sayfasına bakınız .


1
dosya yolu yanı sıra dosya içeriğindeki değişikliği izlemek için bir yolu var mı?
Cam

2
Ben öyle düşünmüyorum. Bu amaçla opensnoop'u kullanabilirsiniz .
sakra

1
Bunu çalışmak için aldım, ama sonra /usr/bin/loggerBash betiğimle değiştirip "<string>path modified</strong>"girişi kaldırdığımda, bash betiğimin masaüstümdeki hangi dosyanın değiştirildiğini bilmesi için herhangi bir yol bulamadım - sadece olay gerçekleşti. Ben bakarken çalıştı $0, $1ve sadece kendisine geçirilen noting, komut dosyası adını kendisi aldı.
16'da Volomike

Ayrıca, bir değişiklik algıladığında, yalnızca bir değişiklik algıladığında başlatmak (ve durdurmak) yerine bir şey algıladı mı? Talep üzerine çalışmayı tercih ederim, örneğin 2 gün önce masaüstümde bir şeylerin değiştiğini ve günlüğe tekrar tekrar yazdığını söyleyen bir döngüde çalışmaya devam etmemeyi tercih ederim. Peki, bu plist'te bir çeşit aralık seçeneği kullanmamız gerekiyor mu?
Volomike

Büyük İş ve Açıklama
ChenSmile

37

Facebook'un bekçisi , Homebrew aracılığıyla da mevcut, güzel görünüyor. Filtrelemeyi de destekler:

Bu iki satır, bir kaynak dizinde bir saat oluşturur ve ardından her CSS dosyası değiştirildiğinde "minify-css" adlı bir aracı çalıştıracak "buildme" adlı bir tetikleyici ayarlar. Araç, değiştirilen dosya adlarının bir listesini geçirecektir.

$ watchman watch ~/src

$ watchman -- trigger ~/src buildme '*.css' -- minify-css

Yolun mutlak olması gerektiğine dikkat edin.


1
Bu açık ara en iyi araçtır.
BentOnCoding

1
Bu çok güzel bir program: Dokümanlar harika, sonsuz bir döngü açmıyor (fswatch'ın yaptığı gibi) ve yeniden başlattıktan sonra oluşturduğunuz saatleri hatırlıyor ve otomatik olarak yeniden başlatıyor.
Brad

21

Küçük aracımı incelemek (ve belki de genişletmek) isteyebilirsiniz kqwait. Şu anda sadece oturuyor ve tek bir dosyada bir yazma olayı bekliyor, ancak kqueue mimarisi hiyerarşik olay istiflemeye izin veriyor ...


Şimdiye kadar dağ aslanı üzerinde çalışıyor. Çok hoş!
Scott

Yani bu gerçekten harika. Küçük bir sorunla karşılaştım fswatch(ki bu da çok iyi, çünkü böyle hafif bir sarıcı da emin olduğum doğru şeyi yapmak için değiştirilebiliyordu) gibi şeyler çalıştırırken git status(aslında her seferinde zsh çalıştırıldığında) istemi benim makine üzerinde işlenir ...) hangi aslında bu ayrıntılı komut dosyası ben sonsuz bir geri besleme döngü oluşturarak vidalar. Ancak kqwait, değiştirilen dosya hakkında bilgi sağlar ve tarafından tetiklenmez git status. Yine de yazmak için ateşe ihtiyacım var.
Steven Lu

2
$ brew install kqwait && while true; do kqwait doc/my_file.md; make; done
Joshua Cook

15

watchdog , dosyaları / dizinleri izlemek için platformlar arası bir python API'sıdır ve olaylar (yeni eklenen dosya, kaldırılan dosya ve değiştirilen dosya dahil) gerçekleştiğinde eylemleri (kabuk komutları dahil) tetiklemenizi sağlayan yerleşik "hileler" aracı içerir.


7

Bu, yalnızca dosyalar değiştiğinde rasgele komutları çalıştırmak için OSX'te entr'den bahsetmektir . Basit ve kullanışlı buluyorum.



3

Düzenleme: fsw ile birleştirildi fswatch. Bu cevapta, herhangi bir referans fswşimdi okunmalıdır fswatch.

Çeşitli iyileştirmeler özellikleri fswatchC ++ adlı bir yedek yazdı fsw:

  • Desteklenen herhangi bir platform (OS X /> = 10.6) üzerine kurulu bir GNU Yapı Sistemi projesidir.

    ./configure && make && sudo make install
    
  • Birden çok yol farklı argümanlar olarak iletilebilir:

    fsw file-0 ... file-n 
    
  • Gibi tüm olay bilgileri ile ayrıntılı bir kayıt dökümü:

    Sat Feb 15 00:53:45 2014 - /path/to/file:inodeMetaMod modified isFile 
    
  • Çıktısının ayrıştırılması kolaydır, böylece fswçıktı başka bir işleme geçirilebilir.

  • Gecikme ile özelleştirilebilir -l, --latency.
  • İle metinsel olanlar yerine sayısal olay bayrakları yazılabilir -n, --numeric.
  • Saat biçimi, strftimebiçim dizeleri kullanılarak özelleştirilebilir -t, --time-format.
  • Saat , makinenin yerel saati (varsayılan olarak) veya ile UTC saati olabilir -u, --utc-time.

FSW Başlarken:

fswolduğu GitHub'dan barındırılan ve depo klonlama elde edilebilir:

    git clone https://github.com/emcrisostomo/fsw

FSW Kurulumu:

fsw aşağıdaki komutlar kullanılarak kurulabilir:

    ./configure && make && sudo make install

Daha fazla bilgi:

Ayrıca, nasıl çalıştığına dair birkaç örnek bulabileceğiniz bir giriş blog yazısı da yazdım fsw.


2

Apple OSX Klasör Eylemleri , bir klasörde gerçekleştirilen eylemlere göre görevleri otomatikleştirmenizi sağlar.


9
Evet biliyorum, bunu birkaç kez kullanmaya çalıştım, asla başarılı bir şekilde işe yaramadı, bana bir örnek verebilir misin?
Nane

1
Bu bir link, cevap değil
Dan Rosenstark

2

Benim fswatch çatalıminotifywait -m biraz daha az işlevsellik sağlar (beklemek yok, daha fazla! Linux ile çok daha fazla sorun var inotifywait...) ayrıştırma dostu çıktı.

Orijinalin üzerinde bir gelişmedir, fswatchçünkü değiştirilen dosyanın gerçek yolunu çatallı bir program sağlamanızı yerine STDOUT üzerinden gönderir.

Bir şeyleri otomatikleştirmek için kullandığım bir dizi korkunç bash komut dosyasının temeli olarak sağlam.

inotifywaitLinux'ta (bu konu dışı) , diğer taraftan, bunun üzerine çok fazla kludge gerektirir ve hala bunu yönetmek için iyi bir yol bulamadım, ancak bence dayalı bir şey node.jsbilet olabilir.


1
Pekala, fswatch çatalı. Mı o Homebrew üzerinde?
fatuhoku

1
Cevap hayır; ama üzerinde çalışıyorlar . Gerçekten hızlı bir şekilde yüklemek için brew install https://raw.github.com/mlevin2/homebrew/116b43eaef08d89054c2f43579113b37b4a2abd3/Library/Formula/fswatch.rb
fatuhoku

1

Bunun için bir GIST var ve kullanımı oldukça basit

watchfiles <cmd> <paths...>

Göstermek için, OR komutu Hello Worldher değiştiğinde aşağıdaki komut yankılanacaktır ; ve varsayılan aralık kontrolü 1 saniyedirfile1file2

watchfiles 'echo Hello World' /path/to/file1 /path/to/file2 

Her 5 saniyede bir kontrol etmek istersem -tbayrağı kullanabilirim

watchfiles -t 'echo Hello World' /path/to/file1 /path/to/file2 
  • -vverbosehata ayıklama bilgilerini gösteren modu etkinleştirir
  • -qyapar watchfilesyürütmek sessizce ( #kullanıcı tanımlı yürütülürken görebilirsiniz gösterilir)
  • -qqmarkaları watchfilestamamen sessizce yürütmek
  • -h yardım ve kullanımı gösterir

https://gist.github.com/thiagoh/5d8f53bfb64985b94e5bc8b3844dba55


0

Bunu macOS için yaptım. Bunun birçok açıdan korkunç olduğuna eminim:

#!/bin/sh
# watchAndRun
if [ $# -ne 2 ]; then
    echo "Use like this:"
    echo "   $0 filename-to-watch command-to-run"
    exit 1
fi
if which fswatch >/dev/null; then
    echo "Watching $1 and will run $2"
    while true; do fswatch --one-event $1 >/dev/null && $2; done
else
    echo "You might need to run: brew install fswatch"
fi

Süre olmadan fswatch sözdizimini bulamadım. Bu sinir bozucu ve betiğin durmasını zorlaştırıyor.
Dan Rosenstark

0

NodeJS kullanmak istiyorsanız , izleme için chokidar (veya aslında chokidar-cli ) adlı bir paket kullanabilir ve ardından rsync(Mac ile birlikte) kullanabilirsiniz:

Rsync komutu:

$ rsync -avz --exclude 'some-file' --exclude 'some-dir' './' '/my/destination'

Chokidar cli (küresel olarak npm ile kurulur):

chokidar \"**/*\" -c \"your-rsync-command-above\"


-3

watchKomutu olmayan ve her 3 saniyede bir komut çalıştırmak isteyen kullanıcılar için basit bir tek satırlı alternatif :

while :; do your-command; sleep 3; done

Temelde aşağıdakileri yapmakla aynı olan sonsuz bir döngüdür:

watch -n3 your-command


3
Bu, dosya sistemindeki olayları dinleyen bir kitaplık kullanmakla aynı DEĞİLDİR. Örneğin, your-commanddisk G / Ç işlemi yapıyorsa, bu her 3 saniyede bir veya saatte 10.800 kez garantili bir disk okuma / yazma işlemidir . Dosya sistemi olaylarını kullanarak, G / Ç'nin (ve diğer pahalı işlemlerin) yalnızca bir dosyayı değiştirdiğinizde (genellikle saatte sadece birkaç kez olduğu) gerçekleşeceği garanti edilir
Noah Sussman

Doğru ve düşünmek güzel. Bir watchşeyin ne yaptığını görmek için genellikle geçici bir süre için bir şeylere ihtiyacım var . Bahsedilen tekniği üretim uygulamaları veya benzeri bir şey için kullanmıyorum. Örneğin, ilerlemesini görmek istiyorum ddve tekniğim bunu gerçekleştiriyor ( your-commanduygun sinyali göndermek için uygun şekilde değiştirerek dd).
trusktr
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.