Saya ingin cara cepat dan sederhana untuk mengeksekusi perintah setiap kali file berubah. Saya menginginkan sesuatu yang sangat sederhana, sesuatu yang akan saya tinggalkan berjalan di terminal dan menutupnya setiap kali saya selesai bekerja dengan file itu.
Saat ini, saya menggunakan ini:
while read; do ./myfile.py ; done
Dan kemudian saya harus pergi ke terminal itu dan tekan Enter, setiap kali saya menyimpan file itu di editor saya. Yang saya inginkan adalah sesuatu seperti ini:
while sleep_until_file_has_changed myfile.py ; do ./myfile.py ; done
Atau solusi lain semudah itu.
BTW: Saya menggunakan Vim, dan saya tahu saya bisa menambahkan perintah otomatis untuk menjalankan sesuatu di BufWrite, tapi ini bukan solusi yang saya inginkan sekarang.
Pembaruan: Saya menginginkan sesuatu yang sederhana, jika mungkin dibuang. Terlebih lagi, saya ingin sesuatu berjalan di terminal karena saya ingin melihat output program (saya ingin melihat pesan kesalahan).
Tentang jawabannya: Terima kasih atas semua jawaban Anda! Semuanya sangat baik, dan masing-masing mengambil pendekatan yang sangat berbeda dari yang lain. Karena saya hanya perlu menerima satu, saya menerima yang sudah saya gunakan (itu sederhana, cepat dan mudah diingat), meskipun saya tahu itu bukan yang paling elegan.
Jawaban:
Sederhana, menggunakan inotifywait (instal
inotify-tools
paket distribusi Anda ):atau
Cuplikan pertama lebih sederhana, tetapi memiliki kelemahan signifikan: ia akan kehilangan perubahan yang dilakukan saat
inotifywait
tidak berjalan (khususnya saatmyfile
sedang berjalan). Cuplikan kedua tidak memiliki cacat ini. Namun, berhati-hatilah karena ini mengasumsikan bahwa nama file tidak mengandung spasi. Jika itu masalah, gunakan--format
opsi untuk mengubah output untuk tidak menyertakan nama file:Either way, ada batasan: jika beberapa program mengganti
myfile.py
dengan file yang berbeda, daripada menulis ke yang sudah adamyfile
,inotifywait
akan mati. Banyak editor bekerja seperti itu.Untuk mengatasi batasan ini, gunakan
inotifywait
pada direktori:Sebagai alternatif, gunakan alat lain yang menggunakan fungsi dasar yang sama, seperti incron (memungkinkan Anda mendaftarkan acara saat file dimodifikasi) atau fswatch (alat yang juga berfungsi pada banyak varian Unix lainnya, menggunakan analog masing-masing varian dari Linux yang tidak diotifikasi).
sumber
sleep_until_modified.sh
skrip yang mudah digunakan , tersedia di: bitbucket.org/denilsonsa/small_scripts/srcwhile sleep_until_modified.sh derivation.tex ; do latexmk -pdf derivation.tex ; done
fantastis. Terima kasih.inotifywait -e delete_self
tampaknya bekerja dengan baik untuk saya.while inotifywait -e close_write myfile.py; do ./myfile.py; done
selalu keluar tanpa menjalankan perintah (bash dan zsh). Agar ini berfungsi, saya perlu menambahkan|| true
, misalnya:while inotifywait -e close_write myfile.py || true; do ./myfile.py; done
entr ( http://entrproject.org/ ) menyediakan antarmuka yang lebih ramah untuk memberitahukan (dan juga mendukung * BSD & Mac OS X).
Itu membuatnya sangat mudah untuk menentukan beberapa file untuk ditonton (dibatasi hanya oleh
ulimit -n
), menghilangkan kerumitan berurusan dengan file yang diganti, dan membutuhkan sintaksis kurang bash:Saya telah menggunakannya di seluruh pohon sumber proyek saya untuk menjalankan tes unit untuk kode yang saya modifikasi saat ini, dan itu sudah merupakan dorongan besar untuk alur kerja saya.
Panji suka
-c
(hapus layar di antara menjalankan) dan-d
(keluar saat file baru ditambahkan ke direktori yang dipantau) menambah lebih banyak fleksibilitas, misalnya yang dapat Anda lakukan:Pada awal 2018 masih dalam pengembangan aktif dan dapat ditemukan di Debian & Ubuntu (
apt install entr
); membangun dari repo penulis itu bebas rasa sakit dalam hal apapun.sumber
-d
bendera baru ; ini sedikit lebih bertele-tele, tetapi Anda bisa lakukanwhile sleep 1 ; do find . -name '*.py' | entr -d ./myfile.py ; done
untuk menangani file baru.brew install entr
akan berfungsi seperti yang diharapkanSaya menulis sebuah program Python untuk melakukan hal ini dengan tepat yang disebut ketika-diubah .
Penggunaannya sederhana:
Atau untuk menonton banyak file:
FILE
bisa berupa direktori. Tonton secara rekursif dengan-r
. Gunakan%f
untuk meneruskan nama file ke perintah.sumber
when-changed FILE 'clear; COMMAND'
.when-changed
sekarang lintas platform! Lihat rilis 0.3.0 terbaru :)Bagaimana dengan skrip ini? Ia menggunakan
stat
perintah untuk mendapatkan waktu akses file dan menjalankan perintah setiap kali ada perubahan dalam waktu akses (setiap kali file diakses).sumber
stat
waktu modifikasi akan lebih baik "setiap kali file berubah" menjawab?vmstat -d
untuk melihat akses disk. Tampaknya linux melakukan pekerjaan yang luar biasa untuk melakukan caching hal ini: DSolusi menggunakan Vim:
Tapi saya tidak ingin solusi ini karena agak menjengkelkan untuk mengetik, agak sulit untuk mengingat apa yang harus diketik, dan agak sulit untuk membatalkan efeknya (perlu dijalankan
:au! BufWritePost myfile.py
). Selain itu, solusi ini memblokir Vim sampai perintah selesai dieksekusi.Saya telah menambahkan solusi ini di sini hanya untuk kelengkapan, karena dapat membantu orang lain.
Untuk menampilkan output program (dan benar-benar mengganggu aliran pengeditan Anda, karena output akan menulis di editor Anda selama beberapa detik, sampai Anda menekan Enter), hapus
:silent
perintah.sumber
entr
(lihat di bawah) - buat saja vim touch file dummy yang sedang ditonton oleh entr, dan biarkan entr melakukan sisanya di latar belakang ... atautmux send-keys
jika Anda berada di lingkungan seperti itu :).vimrc
file AndaJika Anda telah
npm
menginstal,nodemon
mungkin cara termudah untuk memulai, terutama pada OS X, yang tampaknya tidak memiliki alat inotify. Ini mendukung menjalankan perintah ketika folder berubah.sumber
nodemon -x "bundle exec rspec" spec/models/model_spec.rb -w app/models -w spec/models
WatchPaths
kunci seperti yang ditunjukkan pada tautan saya.Bagi mereka yang tidak dapat menginstal
inotify-tools
seperti saya, ini harus bermanfaat:watch -d -t -g ls -lR
Perintah ini akan keluar ketika output berubah,
ls -lR
akan mencantumkan setiap file dan direktori dengan ukuran dan tanggalnya, jadi jika file diubah itu harus keluar dari perintah, seperti yang dikatakan manusia:Saya tahu jawaban ini mungkin tidak dibaca oleh siapa pun, tetapi saya berharap seseorang akan mencapainya.
Contoh baris perintah:
Buka terminal lain:
Sekarang terminal pertama akan di-output
1,2,3
Contoh skrip sederhana:
sumber
watch -d -t -g "ls -lR tmp | sha1sum"
watch from procps-ng 3.3.10
) menerima float detik untuk intervalnya, karenanyawatch -n0.2 ...
akan melakukan polling setiap perlima detik. Bagus untuk tes unit sub-milidetik yang sehat.rerun2
( on github ) adalah skrip Bash 10-baris dari formulir:Simpan versi github sebagai 'jalankan kembali' di PATH Anda, dan panggil menggunakan:
Ini menjalankan PERINTAH setiap kali ada acara memodifikasi sistem file dalam direktori Anda saat ini (rekursif.)
Hal-hal yang mungkin orang sukai tentang itu:
Hal-hal yang orang mungkin tidak suka tentang itu:
Ini adalah penyempurnaan dari jawaban @ cychoi.
sumber
"$@"
alih-alih$@
, agar berfungsi dengan baik dengan argumen yang berisi spasi. Tetapi pada saat yang sama Anda gunakaneval
, yang memaksa pengguna menjalankan kembali ekstra hati-hati saat mengutip.rerun 'command'
. Apakah Anda hanya mengatakan bahwa jika saya menggunakan "$ @", maka pengguna bisa memanggil sebagairerun command
Itu tampaknya tidak berguna bagi saya (tanpa tanda kutip?): Saya biasanya tidak ingin Bash melakukan setiap pengolahan perintah sebelum diteruskan untuk menjalankan kembali. mis. jika perintah mengandung "echo $ myvar", maka saya ingin melihat nilai-nilai baru myvar di setiap iterasi.rerun foo "Some File"
mungkin pecah. Tetapi karena Anda menggunakaneval
, itu dapat ditulis ulang sebagairerun 'foo "Some File"
. Perhatikan bahwa terkadang perluasan jalur mungkin menghasilkan spasi:rerun touch *.foo
kemungkinan akan pecah, dan menggunakanrerun 'touch *.foo'
memiliki semantik yang sedikit berbeda (perluasan jalur hanya terjadi sekali, atau beberapa kali).rerun ls "some file"
pecah karena spasi.rerun touch *.foo*
biasanya berfungsi dengan baik, tetapi gagal jika nama file yang cocok * .foo berisi spasi. Terima kasih telah membantu saya melihatrerun 'touch *.foo'
perbedaan semantik, tetapi saya menduga versi dengan tanda kutip tunggal adalah semantik yang saya inginkan: Saya ingin setiap iterasi tayangan ulang bertindak seolah-olah saya mengetikkan perintah lagi - maka saya ingin*.foo
diperluas pada setiap iterasi . Saya akan mencoba saran Anda untuk memeriksa efeknya ...Berikut ini skrip shell Bourne shell sederhana yang:
Bersihkan setelahnya sendiri saat Anda menekan Rtr-C
Ini berfungsi pada FreeBSD. Satu-satunya masalah portabilitas yang dapat saya pikirkan adalah jika beberapa Unix lain tidak memiliki perintah mktemp (1), tetapi dalam hal ini Anda hanya dapat membuat kode nama file temp yang sulit.
sumber
$cmd
, tetapi untungnya itu mudah diperbaiki: paritcmd
variabel dan jalankan"$@"
. Skrip Anda tidak cocok untuk memantau file besar, tetapi itu bisa diperbaiki dengan mengganticp
dengantouch -r
(Anda hanya perlu tanggal, bukan konten). Dari sisi portabilitas,-nt
tes ini membutuhkan bash, ksh atau zsh.Lihatlah incron . Ini mirip dengan cron, tetapi menggunakan acara yang tidak resmi alih-alih waktu.
sumber
Solusi lain dengan NodeJs, fsmonitor :
Pasang
Dari baris perintah (misalnya, monitor log dan "eceran" jika satu file log berubah)
sumber
tail -F -q *.log
, saya pikir.tail -f
bukanclear
terminal.Lihatlah ke Penjaga, khususnya dengan plugin ini:
https://github.com/hawx/guard-shell
Anda dapat mengaturnya untuk menonton sejumlah pola di direktori proyek Anda, dan menjalankan perintah ketika perubahan terjadi. Kesempatan baik bahkan bahwa ada plugin yang tersedia untuk itu apa yang Anda coba lakukan di tempat pertama.
sumber
jika Anda telah menginstal nodemon , maka Anda dapat melakukan ini:
Dalam kasus saya, saya mengedit html secara lokal dan mengirimkannya ke server jarak jauh saya ketika file berubah.
sumber
Di bawah Linux:
Akan menjalankan perintah setiap 2 detik.
Jika perintah Anda membutuhkan lebih dari 2 detik untuk dijalankan, jam akan menunggu sampai selesai sebelum melakukannya lagi.
sumber
Watchdog adalah proyek Python, dan mungkin hanya apa yang Anda cari:
Baru saja menulis pembungkus baris perintah untuk itu
watchdog_exec
:Contoh berjalan
Pada acara fs yang melibatkan file dan folder dalam direktori saat ini, jalankan
echo $src $dst
perintah, kecuali jika acara fs diubah, kemudian jalankanpython $src
perintah.Menggunakan argumen pendek, dan membatasi untuk hanya mengeksekusi ketika acara melibatkan " main .py":
EDIT: Baru saja ditemukan Watchdog memiliki CLI resmi yang dipanggil
watchmedo
, jadi periksa juga.sumber
Jika program Anda menghasilkan semacam log / output, Anda dapat membuat Makefile dengan aturan untuk log / output yang tergantung pada skrip Anda dan melakukan sesuatu seperti
Sebagai alternatif, Anda dapat membuat target palsu dan memiliki aturan untuk itu baik memanggil skrip Anda dan menyentuh target palsu (sementara masih tergantung pada skrip Anda).
sumber
while sleep 1 ; do something ; done
sedikit lebih baik daripadawhile true ; do something ; sleep 1 ; done
. Setidaknya itu berhenti dengan mudah ketika menekan Ctrl + C.swarminglogic menulis sebuah skrip yang disebut watchfile.sh , juga tersedia sebagai GitHub Gist .
sumber
stat
pada nama file yang diberikan, berjalanmd5sum
pada output, dan menjalankan kembali perintah yang diberikan jika nilai ini berubah. Karena itu Bash, saya curiga ini melakukan pekerjaan yang baik dengan menjalankan perintah yang diberikan persis seperti jika Anda mengetiknya di Bash prompt. (Sebaliknya, sebagian besar solusi di sini yang ditulis dalam bahasa lain akan gagal menjalankan perintah yang, misalnya, berisi alias shell sepertill
)Memperbaiki jawaban Gilles .
Versi ini berjalan
inotifywait
sekali dan memonitor acara (.eg:)modify
sesudahnya. Tersebut yanginotifywait
tidak perlu dieksekusi kembali pada setiap peristiwa yang ditemui.Cepat dan cepat! (bahkan ketika memonitor direktori besar secara rekursif)
sumber
Sedikit lagi di sisi pemrograman, tetapi Anda ingin sesuatu seperti tidak masuk akal . Ada banyak implementasi dalam banyak bahasa, seperti jnotify dan pyinotify .
Pustaka ini memungkinkan Anda untuk memantau file tunggal atau seluruh direktori, dan mengembalikan peristiwa ketika suatu tindakan ditemukan. Informasi yang dikembalikan mencakup nama file, tindakan (buat, ubah, ganti nama, hapus) dan jalur file, di antara informasi bermanfaat lainnya.
sumber
Bagi Anda yang mencari solusi FreeBSD, berikut adalah portnya:
sumber
Saya suka kesederhanaan
while inotifywait ...; do ...; done
namun memiliki dua masalah:do ...;
akan terlewatkanKarenanya saya membuat skrip pembantu yang menggunakan inotifywait tanpa batasan-batasan itu: inotifyexec
Saya sarankan Anda meletakkan skrip ini di jalur Anda, seperti di
~/bin/
. Penggunaan dijelaskan dengan hanya menjalankan perintah.Contoh:
inotifyexec "echo test" -r .
sumber
Solusi Sebastian yang ditingkatkan dengan
watch
perintah:watch_cmd.sh
:Contoh panggilan:
Berhasil tetapi hati-hati:
watch
perintah memiliki bug yang diketahui (lihat man): ia bereaksi terhadap perubahan hanya di VISIBLE di bagian terminal-g CMD
output.sumber
Anda dapat mencoba refleks .
Refleks adalah alat kecil untuk menonton direktori dan menjalankan kembali perintah ketika file tertentu berubah. Ini bagus untuk menjalankan tugas kompilasi / serat / pengujian secara otomatis dan untuk memuat ulang aplikasi Anda ketika kode berubah.
sumber
Jawaban oneliner yang saya gunakan untuk melacak perubahan file:
Anda tidak perlu menginisialisasi BF jika Anda tahu bahwa kencan pertama adalah waktu mulai.
Ini sederhana dan portabel. Ada jawaban lain berdasarkan strategi yang sama menggunakan skrip di sini. Lihatlah juga.
Penggunaan: Saya menggunakan ini untuk men-debug dan mengawasi
~/.kde/share/config/plasma-desktop-appletsrc
; bahwa untuk beberapa alasan yang tidak diketahui terus kehilangan sayaSwitchTabsOnHover=false
sumber
Saya menggunakan skrip ini untuk melakukannya. Saya menggunakan inotify dalam mode monitor
Simpan ini sebagai runatwrite.sh
itu akan menjalankan myfile.sh di setiap tulisan.
sumber
Bagi mereka yang menggunakan OS X, Anda dapat menggunakan LaunchAgent untuk menonton path / file untuk perubahan dan melakukan sesuatu ketika itu terjadi. FYI - LaunchControl adalah aplikasi bagus untuk membuat / memodifikasi / menghapus daemon / agen dengan mudah.
( contoh diambil dari sini )
sumber
Saya punya GIST untuk ini dan penggunaannya cukup sederhana
https://gist.github.com/thiagoh/5d8f53bfb64985b94e5bc8b3844dba55
sumber
Untuk orang-orang yang menemukan ini dengan Googling untuk perubahan pada file tertentu , jawabannya jauh lebih sederhana (terinspirasi oleh jawaban Gilles ).
Jika Anda ingin melakukan sesuatu setelah file tertentu ditulis, berikut caranya:
Simpan ini sebagai, misalnya,
copy_myfile.sh
dan masukkan.sh
file ke/etc/init.d/
folder untuk menjalankannya saat startup.sumber
Alat 'fido' mungkin merupakan pilihan lain untuk kebutuhan ini. Lihat https://www.joedog.org/fido-home/
sumber
Seperti yang telah dilakukan beberapa orang lainnya, saya juga telah menulis alat baris perintah yang ringan untuk melakukan ini. Ini sepenuhnya didokumentasikan, diuji, dan modular.
Watch-Do
Instalasi
Anda dapat menginstalnya (jika Anda memiliki Python3 dan pip) menggunakan:
Pemakaian
Gunakan langsung dengan menjalankan:
Ikhtisar Fitur
-w '*.py'
atau-w '**/*.py'
)-d
bendera lagi)-r
untuk mengaktifkannya)sumber