Apakah ada perintah seperti "menonton" atau "tidak menunggu" di Mac?

287

Saya ingin menonton folder di Mac saya (Snow Leopard) dan kemudian menjalankan skrip (memberikannya nama file dari apa yang baru saja dipindahkan ke folder (sebagai parameter ... x.sh "nama file")).

Saya memiliki semua skrip ditulis dalam bash (x.sh) yang akan memindahkan beberapa file dan hal-hal lain pada input $ 1. Saya hanya perlu OSX untuk memberi saya nama file ketika file / folder baru dipindahkan / dibuat menjadi dir.

Ada perintah seperti itu?

daun mint
sumber
1
Anda harus bertanya bagaimana DropBox melakukannya karena mungkin mereka mencoba semua opsi yang tersedia.
Jeff Burdges
2
@JeffBurdges Saya tidak begitu yakin itu akan mudah. Namun saya akan mengatakan setelah membaca Referensi FSEvents Apple akan sangat konyol jika Dropbox tidak menggunakan ini. The fswatchutil disajikan sebagai jawaban di bawah ini sebenarnya tidak menggunakan metode ini.
Steven Lu

Jawaban:

447

fswatch

fswatch adalah program kecil menggunakan Mac OS X FSEvents API untuk memantau direktori. Ketika suatu peristiwa tentang perubahan apa pun ke direktori itu diterima, perintah shell yang ditentukan dijalankan oleh/bin/bash

Jika Anda menggunakan GNU / Linux, inotifywatch (bagian dari inotify-toolspaket di sebagian besar distribusi) menyediakan fungsionalitas serupa.

Pembaruan: fswatch sekarang dapat digunakan di banyak platform termasuk BSD, Debian, dan Windows.

Sintaks / Contoh Sederhana

Cara baru yang dapat menonton banyak jalur - untuk versi 1.x dan lebih tinggi :

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

Catatan: Angka keluaran oleh -oakan ditambahkan ke akhir xargsperintah jika bukan untuk -I{}. Jika Anda memilih untuk menggunakan nomor itu, letakkan {}di mana saja dalam perintah Anda.

Cara yang lebih lama untuk versi 0.x :

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

Instalasi dengan Homebrew

Pada 9/12/13 ditambahkan kembali ke homebrew - yay! Jadi, perbarui daftar rumus Anda ( brew update) dan kemudian yang perlu Anda lakukan adalah:

brew install fswatch

Instalasi tanpa Homebrew

Ketik perintah ini di Terminal.app

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

Jika Anda tidak memiliki ckompiler pada sistem Anda, Anda mungkin perlu menginstal alat baris perintah Xcode atau Xcode - keduanya gratis. Namun, jika itu masalahnya, Anda mungkin harus memeriksa homebrew .

Opsi tambahan untuk fswatchversi 1.x

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.
cwd
sumber
Instruksi Anda atau menginstal tanpa homebrew tampaknya tidak berfungsi lagi. makemelempar kesalahan tentang tidak menemukan makefile. Untungnya, fswatch sekarang ada di MacPorts, jadi sudo port install fswatchberfungsi, bagi kita yang menggunakan MacPorts, bukan Homebrew.
coredumperror
Jika Anda menggunakan perintah dengan argumen statis (misalnya, saya menjalankan tes unit saya di src dan menguji perubahan) ini mungkin tidak berfungsi untuk Anda. Pertanyaan ini ( stackoverflow.com/questions/25689589/… ) adalah bagian kedua yang saya butuhkan.
jskulski
5
Saya mendengar Anda di luar sana:fswatch ./ | xargs -I{} cp {} ~/Dropbox/backup/latest/
fionbio
fswatch lebih baik daripada alat seperti entr atau when_changed, yang memiliki beberapa bug ketika berhadapan dengan direktori .git. fswatch jauh lebih profesional. Cukup, Anda hanya fswatch .akan memantau direktori saat ini.
anonim
Saya akan menyarankan fswatch -0 -v -o /path/to/watched/files | xargs -0 -n 1 -I {} [your command]dengan -0untuk NULLs. Yang ini berfungsi untuk saya untuk kompilasi yang kurang
boldnik
95

Anda dapat menggunakan launchd untuk tujuan itu. Launchd dapat dikonfigurasikan untuk secara otomatis meluncurkan program ketika path file diubah.

Sebagai contoh, daftar konfigurasi launchd berikut akan meluncurkan program /usr/bin/loggerketika folder desktop dari akun pengguna saya dimodifikasi:

<?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>

Untuk mengaktifkan config plist, simpan ke folder LaunchAgents di folder Library Anda sebagai "logger.plist".

Dari shell Anda kemudian dapat menggunakan perintah launchctluntuk mengaktifkan logger.plist dengan menjalankan:

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

Folder desktop sekarang sedang dipantau. Setiap kali diubah, Anda akan melihat output di system.log (gunakan Console.app). Untuk menonaktifkan logger.plist, jalankan:

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

File konfigurasi di atas menggunakan WatchPathsopsi. Atau Anda juga dapat menggunakan QueueDirectoriesopsi. Lihat halaman manual launchd untuk informasi lebih lanjut.

sakra
sumber
1
apakah ada cara untuk memantau perubahan konten file serta jalur file?
Cam
2
Saya kira tidak. Anda dapat menggunakan opensnoop untuk tujuan itu.
sakra
1
Saya berhasil, tetapi kemudian ketika saya beralih /usr/bin/loggerdengan skrip Bash saya dan menghapus "<string>path modified</strong>"entri, saya tidak dapat menemukan cara apa pun untuk skrip bash saya untuk mengetahui file mana di desktop saya yang dimodifikasi - hanya saja peristiwa itu terjadi. Saya mencoba melihat $0, $1dan hanya mendapatkan nama skrip itu sendiri, mencatat berlalu.
Volomike
Juga, apakah benda ini masuk ke loop setelah mendeteksi perubahan, bukan hanya meluncurkan (dan berhenti) ketika mendeteksi perubahan? Saya lebih suka bekerja sesuai permintaan, tidak terus berjalan dalam satu lingkaran memberitahu saya bahwa, misalnya, 2 hari yang lalu, sesuatu berubah pada desktop saya, menulis itu di log berulang-ulang. Jadi, apakah kita perlu menggunakan semacam opsi interval dalam daftar ini?
Volomike
Great Work and Explanantion
ChenSmile
37

Penjaga Facebook , tersedia melalui Homebrew, juga terlihat bagus. Ini mendukung juga penyaringan:

Dua baris ini membuat arloji pada direktori sumber dan kemudian mengatur pemicu bernama "buildme" yang akan menjalankan alat bernama "minify-css" setiap kali file CSS diubah. Alat akan melewati daftar nama file yang diubah.

$ watchman watch ~/src

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

Perhatikan bahwa jalan harus mutlak.

Jakub Holý
sumber
1
Sejauh ini, ini adalah alat terbaik.
BentOnCoding
1
Ini adalah program kecil yang sangat bagus: Dokumennya bagus, tidak membuka perulangan tak terbatas (yang tampaknya dilakukan fswatch) dan mengingat jam tangan yang Anda buat setelah reboot dan otomatis menyalakannya kembali.
Brad
21

Anda mungkin ingin melihat (dan mungkin memperluas) alat kecil saya kqwait. Saat ini ia hanya duduk dan menunggu acara tulis pada satu file, tetapi arsitektur kqueue memungkinkan untuk susun acara hirarkis ...

sschober
sumber
Bekerja sejauh ini di singa gunung. Sangat bagus!
Scott
Jadi ini sebenarnya sangat luar biasa. Saya mengalami masalah kecil dengan fswatch(yang juga baik-baik saja, karena itu seperti pembungkus cahaya itu juga dapat dimodifikasi untuk melakukan hal yang benar saya yakin) di mana ia akan menyala ketika menjalankan hal-hal sepertigit status (yang sebenarnya dijalankan setiap kali zsh prompt diberikan pada mesin saya ...) yang sebenarnya agak mengacaukan skrip rumit ini yang saya miliki dengan membuat umpan balik tanpa akhir. kqwait, bagaimanapun, memberikan info tentang file yang diubah, dan tidak tersandung oleh git status. Saya membutuhkannya untuk menulis.
Steven Lu
2
$ brew install kqwait && while true; do kqwait doc/my_file.md; make; done
Joshua Cook
15

watchdog adalah API python lintas-platform untuk menonton file / direktori, dan telah dibangun di dalam alat "trik" yang memungkinkan Anda untuk memicu tindakan (termasuk perintah shell) ketika peristiwa terjadi (termasuk file baru yang ditambahkan, file yang dihapus dan file yang diubah).

gfxmonk
sumber
7

Ini hanya untuk menyebutkan entr sebagai alternatif pada OSX untuk menjalankan perintah sewenang-wenang ketika file berubah. Saya merasa sederhana dan bermanfaat.

Donny Winston
sumber
5

Berikut ini adalah one-liner using sschober's tool .

$ while true; do kqwait ./file-to-watch.js; script-to-execute.sh; done
Joshua Cook
sumber
$ brew install kqwait
Joshua Cook
3

Sunting: fsw telah digabung menjadi fswatch. Dalam jawaban ini, referensi apa pun fswharus sekarang dibacafswatch .

Saya menulis fswatchpengganti di C ++ yang disebut fswfitur beberapa perbaikan:

  • Ini adalah proyek Sistem Bangun GNU yang dibangun di atas platform apa pun yang didukung (OS X v.> = 10.6) dengan

    ./configure && make && sudo make install
    
  • Beberapa jalur dapat dilewatkan sebagai argumen yang berbeda:

    fsw file-0 ... file-n 
    
  • Itu membuang catatan rinci dengan semua informasi acara seperti:

    Sat Feb 15 00:53:45 2014 - /path/to/file:inodeMetaMod modified isFile 
    
  • Outputnya mudah diurai sehingga fswoutput dapat disalurkan ke proses lain.

  • Latensi dapat disesuaikan dengan -l, --latency .
  • Bendera peristiwa numerik dapat ditulis alih-alih yang tekstual dengan -n, --numeric .
  • Format waktu dapat dikustomisasi menggunakan strftimestring format dengan -t, --time-format.
  • Waktu dapat berupa waktu lokal mesin (secara default) atau waktu UTC dengan -u, --utc-time.

Mendapatkan fsw:

fswdi- host di GitHub dan dapat diperoleh kloning repositori-nya:

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

Menginstal fsw:

fsw dapat diinstal menggunakan perintah berikut:

    ./configure && make && sudo make install

Informasi lebih lanjut:

Saya juga menulis posting blog pengantar di mana Anda dapat menemukan beberapa contoh tentang cara fswkerjanya.

Enrico M. Crisostomo
sumber
2

Tindakan Folder Apple OSX memungkinkan Anda untuk mengotomatisasi tugas berdasarkan tindakan yang diambil pada folder.

Asaf
sumber
9
Ya saya tahu, saya sudah mencoba menggunakannya beberapa kali, tidak pernah berhasil membuatnya bekerja, bisakah Anda memberi saya contoh?
Mint
1
Itu tautan, bukan jawaban
Dan Rosenstark
2

Garpu fswatch saya menyediakan fungsionalitas inotifywait -mdengan sedikit lebih sedikit (jangan menunggu, lebih! Saya punya banyak masalah di Linux dengan inotifywait...) keluaran parse-friendly.

Ini merupakan perbaikan dari yang asli fswatch karena mengirimkan jalur sebenarnya dari file yang diubah melalui STDOUT daripada mengharuskan Anda untuk menyediakan program yang dibuatnya.

Sudah solid sebagai dasar dari serangkaian skrip bash menakutkan yang saya gunakan untuk mengotomatisasi hal-hal.

(ini di luar topik) inotifywaitdi Linux, di sisi lain, membutuhkan banyak kludges di atasnya dan saya masih belum menemukan cara yang baik untuk mengelolanya, meskipun saya pikir sesuatu yang didasarkan pada node.jsmungkin tiketnya.

Steven Lu
sumber
1
Benar, garpu fswatch. Apakah itu di Homebrew?
fatuhoku
1
Jawabannya adalah tidak; tapi mereka sedang mengusahakannya . Untuk menginstalnya dengan sangat cepat brew install https://raw.github.com/mlevin2/homebrew/116b43eaef08d89054c2f43579113b37b4a2abd3/Library/Formula/fswatch.rb
fatuhoku
1

Saya punya GIST untuk ini dan penggunaannya cukup sederhana

watchfiles <cmd> <paths...>

Sebagai ilustrasi, perintah berikut akan menggema Hello Worldsetiap kali file1ATAU file2berubah; dan pemeriksaan interval default adalah 1 detik

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

Jika saya ingin memeriksa setiap 5 detik saya bisa menggunakan -tbendera

watchfiles -t 'echo Hello World' /path/to/file1 /path/to/file2 
  • -vmengaktifkan verbosemode yang menampilkan informasi debug
  • -qmembuat watchfileseksekusi dengan diam-diam ( #akan ditampilkan sehingga pengguna dapat melihat program mengeksekusi)
  • -qqmembuat watchfileseksekusi sepenuhnya dengan tenang
  • -h menunjukkan bantuan dan penggunaan

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

thiagoh
sumber
0

Saya akhirnya melakukan ini untuk macOS. Saya yakin ini mengerikan dalam banyak hal:

#!/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
Dan Rosenstark
sumber
Saya tidak bisa mengetahui sintaks fswatch tanpa waktu. Yang menjengkelkan dan membuat skrip sulit dihentikan.
Dan Rosenstark
0

Jika Anda ingin menggunakan NodeJS, Anda dapat menggunakan paket yang disebut chokidar (atau chokidar-cli sebenarnya) untuk menonton dan kemudian menggunakanrsync (disertakan dengan Mac):

Perintah Rsync:

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

Cli Chokidar (diinstal secara global melalui npm):

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

prograhammer
sumber
-3

Berikut adalah alternatif baris tunggal sederhana untuk pengguna yang tidak memiliki watchperintah yang ingin menjalankan perintah setiap 3 detik:

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

Ini adalah infinite loop yang pada dasarnya sama dengan melakukan hal berikut:

watch -n3 your-command

trusktr
sumber
3
Ini BUKAN sama dengan menggunakan perpustakaan yang mendengarkan acara dari sistem file. Jika dalam contoh Anda, your-commandapakah disk I / O, maka itu disk dijamin baca / tulis setiap 3 detik - atau 10.800 kali setiap jam. Dengan menggunakan peristiwa filesystem Anda akan dijamin bahwa I / O (dan operasi mahal lainnya) hanya terjadi ketika Anda mengubah file (yang umumnya hanya beberapa kali dalam satu jam.)
Noah Sussman
Benar, dan bagus untuk dipertimbangkan. Saya biasanya perlu watchuntuk sementara waktu untuk melihat apa yang dilakukan sesuatu. Saya tidak menggunakan teknik yang saya sebutkan untuk aplikasi produksi atau semacamnya. Misalnya, saya ingin melihat perkembangannya dd, dan teknik saya mewujudkannya (menggantikan yang your-commandsesuai untuk mengirim sinyal yang sesuai dd).
trusktr