ファイルが変更されるたびにコマンドを実行する方法は?


434

ファイルが変更されるたびにコマンドを実行するための迅速かつ簡単な方法が必要です。非常にシンプルなものが欲しいです。ターミナルで実行したままにして、そのファイルでの作業が終了したらいつでも閉じます。

現在、私はこれを使用しています:

while read; do ./myfile.py ; done

そして、Enterそのファイルをエディターに保存するたびに、そのターミナルに移動してを押す必要があります。私が欲しいのは次のようなものです:

while sleep_until_file_has_changed myfile.py ; do ./myfile.py ; done

または、それと同じくらい簡単な他のソリューション。

ところで、私はVimを使用しています。BufWriteで何かを実行するためのオートコマンドを追加できることは知っていますが、これは私が今求めている種類のソリューションではありません。

更新:可能な場合は廃棄可能なシンプルなものが必要です。さらに、プログラムの出力を確認したい(エラーメッセージを確認したい)ため、ターミナルで何かを実行したい。

回答について:回答ありがとうございます!それらはすべて非常に優れており、それぞれが他のアプローチとは非常に異なるアプローチを取っています。私は1つだけを受け入れる必要があるので、最もエレガントではないことがわかっていても、実際に使用したものを受け入れています(シンプルで、素早く、覚えやすい)。


可能性のあるクロスサイト重複:stackoverflow.com/questions/2972765/...(ここではそれが話題になるが=))
チロSantilli新疆改造中心法轮功六四事件

クロスサイトの複製の前に参照しましたが、拒否されました:S;)
フランシスコタピア

4
Jonathan Hartleyによるソリューションは、ここでの他のソリューションに基づいて構築されており、上位投票の回答にある大きな問題を修正します。受け入れられている回答を変更してください。これは、github.com / tartley / rerun2の github (またはこれらの欠陥のない他のソリューション)でも保守されています
nealmcb

回答:


404

シンプル、inotifywaitを使用(ディストリビューションのinotify-toolsパッケージをインストール):

while inotifywait -e close_write myfile.py; do ./myfile.py; done

または

inotifywait -q -m -e close_write myfile.py |
while read -r filename event; do
  ./myfile.py         # or "./$filename"
done

最初のスニペットは単純ですが、重大な欠点inotifywaitがありmyfileます。実行されていない間(特に実行中)に実行された変更が失われます。2番目のスニペットにはこの欠陥はありません。ただし、ファイル名に空白が含まれていないと想定していることに注意してください。問題がある場合は、--formatオプションを使用して出力を変更し、ファイル名を含めないようにします。

inotifywait -q -m -e close_write --format %e myfile.py |
while read events; do
  ./myfile.py
done

いずれにせよ、制限があります。あるプログラムがmyfile.py別のファイルに置き換えられた場合、既存のmyfileに書き込むのではなく、inotifywait死にます。多くの編集者がそのように機能します。

この制限を克服するinotifywaitには、ディレクトリで次を使用します。

inotifywait -e close_write,moved_to,create -m . |
while read -r directory events filename; do
  if [ "$filename" = "myfile.py" ]; then
    ./myfile.py
  fi
done

あるいは、incron(ファイルが変更されたときにイベントを登録できるようにする)やfswatch(各バリアントのLinuxのinotifyの類似体を使用して、他の多くのUnixバリアントでも機能するツール)など、同じ基本機能を使用する別のツールを使用します。


46
私は、簡単に使用中(かなりの数のbashのトリックで)このすべてのカプセル化されましたsleep_until_modified.sh:で入手可能なスクリプト、bitbucket.org/denilsonsa/small_scripts/src
デニウソンSáマイア

14
while sleep_until_modified.sh derivation.tex ; do latexmk -pdf derivation.tex ; done素晴らしい。ありがとうございました。
リースウレリッチ

5
inotifywait -e delete_self私にとってはうまくいくようです。
コス

3
単純ですが、2つの重要な問題があります。イベントが失われる可能性があり(ループ内のすべてのイベント)、inotifywaitの初期化が毎回行われるため、このソリューションは大きな再帰フォルダーに対して遅くなります。
ワーナイト14

6
何らかの理由でwhile inotifywait -e close_write myfile.py; do ./myfile.py; done、コマンド(bashおよびzsh)を実行せずに常に終了します。これを機能させるには、次を追加する必要がありました|| true。例: while inotifywait -e close_write myfile.py || true; do ./myfile.py; done
ideasman42

166

entrhttp://entrproject.org/)は、inotifyへのより使いやすいインターフェースを提供します(* BSDおよびMac OS Xもサポートします)。

監視する複数のファイルを指定するのが非常に簡単になり(のみで制限されますulimit -n)、置き換えられるファイルの処理に手間がかからず、必要なbash構文が少なくなります。

$ find . -name '*.py' | entr ./myfile.py

プロジェクトソースツリー全体でこれを使用して、現在変更中のコードの単体テストを実行していますが、これは既にワークフローを大幅に向上させています。

-c(実行間で画面をクリアする)や-d(監視対象ディレクトリに新しいファイルが追加されたときに終了する)などのフラグは、さらに柔軟性を高めます。たとえば、次のことができます。

$ while sleep 1 ; do find . -name '*.py' | entr -d ./myfile.py ; done

2018年初頭現在、まだ活発に開発されており、Debian&Ubuntu(apt install entr)にあります。著者のレポジトリからの構築は、いずれにしても痛みがありませんでした。


3
新しいファイルとその変更を処理しません。
ワーナイト14

2
@Wernight-2014年5月7日現在、entrには新しい-dフラグがあります。少し長めですがwhile sleep 1 ; do find . -name '*.py' | entr -d ./myfile.py ; done、新しいファイルに対処することができます。
ポールフェニー

1
entrは少なくともdebian jessie / 8.2以降のdebianリポジトリでも利用可能です。
Peter V.Mørch15年

5
確かにOS Xで見つけた最高のもの。fswatchは、あまりにも多くのファンキーなイベントをつかみ、私はしたいが、その理由を把握するために時間を費やすいけない
DTC

5
これは、ことは注目に値するENTRは自作で提供されていますので、brew install entr期待どおりに動作します
jmarceli

108

これを正確に行うためのwhen-changedというPythonプログラムを作成しました

使い方は簡単です:

when-changed FILE COMMAND...

または、複数のファイルを見るには:

when-changed FILE [FILE ...] -c COMMAND

FILEディレクトリにすることができます。で再帰的に見る-r%fファイル名をコマンドに渡すために使用します。


1
@ysangkokはい、コードの最新バージョンでは:)
joh

4
「pip install when-changed」から利用できるようになりました。それでもうまくいきます。ありがとう。
ALフラナガン

2
最初に画面をクリアするには、を使用できますwhen-changed FILE 'clear; COMMAND'
デイブジェームスミラー

1
私もWindowsでできるので、この答えははるかに優れています。そして、この男は実際に答えを得るためのプログラムを書いた。
ウルフパック

4
皆さん、朗報です!when-changedクロスプラットフォームになりました!最新の0.3.0リリースを確認してください:)
joh

52

このスクリプトはどうですか?statコマンドを使用してファイルのアクセス時間を取得し、アクセス時間に変更があるたびに(ファイルにアクセスするたびに)コマンドを実行します。

#!/bin/bash

### Set initial time of file
LTIME=`stat -c %Z /path/to/the/file.txt`

while true    
do
   ATIME=`stat -c %Z /path/to/the/file.txt`

   if [[ "$ATIME" != "$LTIME" ]]
   then    
       echo "RUN COMMAND"
       LTIME=$ATIME
   fi
   sleep 5
done

2
ではないだろうstat「ファイルの変更はいつでも」答え方が良い修正時間を-ing?
Xen2050

1
1秒間に何度もstatを実行すると、ディスクへの読み取りが多くなりますか?または、fstatシステムコールはこれらの応答を何らかの形で自動的にキャッシュしますか?私は変更を加えるたびに私のCコードをコンパイルする「イサキ時計」のようなものを書くためにしようとしている
Oskensoカシュガル

これは、事前に監視するファイル名がわかっている場合に便利です。ファイル名をスクリプトに渡す方が良いでしょう。さらに良いのは、多くのファイル名を渡すことができる場合です(例: "mywatch * .py")。さらに良いのは、サブディレクトリ内のファイルに対しても再帰的に操作できる場合です。他のソリューションのいくつかはそうします。
ジョナサンハートリー

5
誰かが大量の読み取りについて疑問に思っている場合に備えて、このスクリプトをUbuntu 17.04で0.05秒のスリープでテストし、 vmstat -dディスクアクセスを監視しました。Linuxはこの種のことをキャッシュするのに素晴らしい仕事をしているようです:D
Oskenso Kashi

「COMMAND」にタイプミスがあり、修正しようとしていましたが、SOは「編集は6文字未満であってはなりません」と言います
-user337085

30

Vimを使用したソリューション:

:au BufWritePost myfile.py :silent !./myfile.py

しかし、このソリューションは、入力するのが面倒で、何を入力するのかを正確に覚えるのが少し難しく、その効果を元に戻すのが難しい(実行する必要がある:au! BufWritePost myfile.py)ため、このソリューションは必要ありません。さらに、このソリューションは、コマンドの実行が完了するまでVimをブロックします。

他の人にも役立つかもしれないので、ここでは完全を期すためにこのソリューションを追加しました。

プログラム出力を表示するには(また、Enterキーを押すまで出力が数秒間エディターに上書きされるため、編集フローを完全に中断します)、:silentコマンドを削除します。


1
これと組み合わせると非常に便利ですentr(以下を参照)-entrが監視しているダミーファイルにvimをタッチし、entrにバックグラウンドで残りの作業をさせます...またはtmux send-keys、そのような環境にいる場合:)
ポールフェニー

いいね!.vimrcファイルのマクロを作成できます
ErichBSchulz

23

npmインストールしたことがある場合nodemonは、おそらく、特にinotifyツールを持たないOS Xで開始する最も簡単な方法です。フォルダーが変更されたときにコマンドを実行できます。


5
ただし、.jsおよび.coffeeファイルのみを監視します。
ゼルク

6
現在のバージョンは、たとえば次のようなコマンドをサポートしているようです nodemon -x "bundle exec rspec" spec/models/model_spec.rb -w app/models -w spec/models
。– kek

1
fsevents、私はより多くの情報を持っていたいが、OSXの変更を追跡する方法を持っている
ConstantineK

1
OS X では、リンクに示されているキーでLaunch Daemonsを使用することもできますWatchPaths
アダムジョンズ14年

19

inotify-tools私のようにインストールできない人にとって、これは役に立つはずです:

watch -d -t -g ls -lR

このコマンドは、出力が変更されると終了し、ls -lRすべてのファイルとディレクトリのサイズと日付を一覧表示します。そのため、ファイルが変更された場合は、コマンドを終了する必要があります。

-g, --chgexit
          Exit when the output of command changes.

この答えは誰にも読まれないかもしれませんが、誰かがそれに到達することを望みます。

コマンドラインの例:

~ $ cd /tmp
~ $ watch -d -t -g ls -lR && echo "1,2,3"

別のターミナルを開きます:

~ $ echo "testing" > /tmp/test

これで、最初の端末が出力されます 1,2,3

簡単なスクリプトの例:

#!/bin/bash
DIR_TO_WATCH=${1}
COMMAND=${2}

watch -d -t -g ls -lR ${DIR_TO_WATCH} && ${COMMAND}

5
いいハック。テストした結果、リストが長く、変更されたファイルが画面外にある場合、問題があるようです。小さな変更は、このようなものが考えられます。 watch -d -t -g "ls -lR tmp | sha1sum"
Atle

3
あなたはあなたのソリューションは、毎秒を見れば、それは永遠に動作し、唯一のいくつかのファイルが変更された場合MY_COMMAND実行します。-n1「見-d -t -gのls -lR && MY_COMMAND」観る
mnesarco

私のバージョンの時計(Linuxではwatch from procps-ng 3.3.10)は、その間隔にfloat秒を受け入れます。したがってwatch -n0.2 ...、5 秒ごとにポーリングします。これらの健全なサブミリ秒単位テストに適しています。
ジョナサンハートリー

15

rerun2github)は、次の形式の10行のBashスクリプトです。

#!/usr/bin/env bash

function execute() {
    clear
    echo "$@"
    eval "$@"
}

execute "$@"

inotifywait --quiet --recursive --monitor --event modify --format "%w%f" . \
| while read change; do
    execute "$@"
done

githubバージョンをPATHに「再実行」として保存し、次を使用して起動します。

rerun COMMAND

現在のディレクトリ内にファイルシステム変更イベントがあるたびに(再帰的に)コマンドを実行します。

それについて好きなもの:

  • inotifyを使用するため、ポーリングよりも応答性が高くなります。「保存」を押すたびに、サブミリ秒の単体テストを実行したり、graphvizドットファイルをレンダリングしたりするのに最適です。
  • 非常に高速であるため、パフォーマンス上の理由だけで大きなサブディレクトリ(node_modulesなど)を無視するように指示する必要はありません。
  • これは、実行時にではなく、起動時にinotifywaitを1回だけ呼び出し、繰り返しを行うたびにウォッチを確立するという高価なヒットを被るので、非常に応答性に優れています。
  • Bashは12行だけです
  • Bashであるため、Bashプロンプトで入力したかのように、ユーザーが渡したコマンドを正確に解釈します。(おそらく、別のシェルを使用する場合、これはあまりクールではありません。)
  • このページの他のほとんどのinotifyソリューションとは異なり、COMMANDの実行中に発生するイベントは失われません。
  • 最初のイベントでは、0.15秒間「デッド期間」に入ります。その間、COMMANDが1回だけ実行されるまで、他のイベントは無視されます。これは、バッファを保存するときにViまたはEmacsが行うcreate-write-moveダンスによって引き起こされるイベントの急増によって、実行速度の遅いテストスイートの複数の面倒な実行が発生しないようにするためです。COMMANDの実行中に発生するイベントは無視されません。2番目のデッド期間とその後の実行が発生します。

嫌いなもの:

  • inotifyを使用するため、Linuxland以外では機能しません。
  • inotifyを使用しているため、ユーザーのinotifyウォッチの最大数よりも多くのファイルを含むディレクトリをウォッチしようとすることは禁止されます。デフォルトでは、これは私が使用するさまざまなマシンで約5,000から8,000に設定されているようですが、簡単に増やすことができます。https://unix.stackexchange.com/questions/13751/kernel-inotify-watch-limit-reachedを参照してください
  • Bashエイリアスを含むコマンドの実行に失敗します。これが機能していたことを誓うことができました。原則として、これはBashであり、サブシェルでCOMMANDを実行しないため、これが機能することを期待しています。誰かがそれを知らない理由を知っているなら、私は聞きたい。このページの他のソリューションの多くは、このようなコマンドも実行できません。
  • 個人的には、実行中の端末でキーを押して、COMMANDを手動で追加実行できるようにしたかったのです。どういうわけかこれを簡単に追加できますか?同時に実行される「while read -n1」ループも実行しますか?
  • 今、私はそれをコーディングして、ターミナルをクリアし、各反復で実行されたコマンドを出力します。コマンドラインフラグを追加して、このようなことをオフにするなどする人もいるかもしれません。しかし、これにより、サイズと複雑さが大幅に増加します。

これは@cychoiの答えの改良版です。


2
スペースを含む引数を適切に処理する"$@"には$@、の代わりにを使用する必要があると思います。しかし、同時にを使用するとeval、再実行のユーザーがクォートする際に特に注意する必要があります。
デニルソンサマイア

ありがとうデニルソン。引用を慎重に行う必要がある場合の例を挙げていただけますか?私はそれを最後の24時間を使用してきたし、これまでスペースの問題を見ていない、また慎重に何を引用-同じように呼び出されましたrerun 'command'。あなたはちょうど私が「$ @を」を使用した場合、そのユーザーとして呼び出すことができると言っているrerun commandそれは私のためとして有用でいないようだ(引用符なし?):私は、一般的にバッシュはしたくないすべてのそれを渡す前に、コマンドの処理を再実行します。たとえば、コマンドに「echo $ myvar」が含まれている場合、各反復でmyvarの新しい値を確認する必要があります。
ジョナサンハートリー

1
何かrerun foo "Some File"が壊れるかもしれません。ただし、使用しているevalので、に書き換えることができますrerun 'foo "Some File"。パス展開によってスペースが導入される場合があることに注意してください。rerun touch *.foo壊れる可能性があり、使用するrerun 'touch *.foo'セマンティクスはわずかに異なります(パス展開は1回のみ、または複数回行われます)。
デニルソンサマイア

助けてくれてありがとう。うん:rerun ls "some file"スペースのために壊れます。rerun touch *.foo*通常は正常に動作しますが、*。fooに一致するファイル名にスペースが含まれていると失敗します。rerun 'touch *.foo'セマンティクスが異なることを確認してくれてありがとう、しかし私はシングルクォートで囲まれたバージョンが私が望むセマンティクスだと思います:私はコマンドをもう一度入力したかのように再実行の各反復が動作するようにしたい -したがって*.foo、各反復で展開したい。私は...彼らの影響を調べるためにあなたの提案を試してみましょう
ジョナサン・ハートリー

このPR(github.com/tartley/rerun2/pull/1)およびその他に関する詳細。
ジョナサンハートリー

12

以下に、単純なシェルBourneシェルスクリプトを示します。

  1. 2つの引数を取ります:監視するファイルとコマンド(必要に応じて引数付き)
  2. 監視しているファイルを/ tmpディレクトリにコピーします
  3. 2秒ごとに、監視しているファイルがコピーよりも新しいかどうかを確認します
  4. 新しい場合は、コピーを新しいオリジナルで上書きし、コマンドを実行します
  5. Ctr-Cを押すと、自動的にクリーンアップされます

    #!/bin/sh  
    f=$1  
    shift  
    cmd=$*  
    tmpf="`mktemp /tmp/onchange.XXXXX`"  
    cp "$f" "$tmpf"  
    trap "rm $tmpf; exit 1" 2  
    while : ; do  
        if [ "$f" -nt "$tmpf" ]; then  
            cp "$f" "$tmpf"  
            $cmd  
        fi  
        sleep 2  
    done  
    

これはFreeBSDで動作します。私が考えることができる唯一の移植性の問題は、他のUnixにmktemp(1)コマンドがない場合ですが、その場合は一時ファイル名をハードコーディングするだけです。


9
ポーリングは唯一の移植可能な方法ですが、ほとんどのシステムにはファイル変更通知メカニズムがあります(Linuxではintify、FreeBSDではkqueueなど)。引用を行う$cmdと深刻な問題が発生しますが、幸いなことに簡単に修正cmdでき"$@"ます。変数を捨てて実行します。あなたのスクリプトは、大きなファイルを監視するためには適していませんが、それは交換することによって修正される可能性がcptouch -r(日付のみではなく、内容が必要)。移植性に関しては、-ntテストにはbash、kshまたはzshが必要です。
ジル


6

NodeJを使用した別のソリューションfsmonitor

  1. インストール

    sudo npm install -g fsmonitor
    
  2. コマンドラインから(例、ログを監視し、1つのログファイルが変更された場合は「小売」)

    fsmonitor -s -p '+*.log' sh -c "clear; tail -q *.log"
    

補足:この例はで解決できるとtail -F -q *.log思います。
フォルカーシーゲル

これは単なる例でtail -fありclear、端末ではありません。
Atika

6

特にこのプラグインを使用して、Guardを調べます。

https://github.com/hawx/guard-shell

プロジェクトのディレクトリ内の任意の数のパターンを監視し、変更が発生したときにコマンドを実行するように設定できます。そもそもあなたがやろうとしていることのために利用可能なプラグインがあるという可能性もあります。


6

nodemonがインストールされている場合、これを実行できます。

nodemon -w <watch directory> -x "<shell command>" -e ".html"

私の場合、htmlをローカルで編集し、ファイルが変更されたときにリモートサーバーに送信します。

nodemon -w <watch directory> -x "scp filename jaym@jay-remote.com:/var/www" -e ".html"

6

Linuxの場合:

man watch

watch -n 2 your_command_to_run

2秒ごとにコマンドを実行します。

コマンドの実行に2秒以上かかる場合、watchは完了するまで待機してから再度実行します。


それはかなり単純ですが、多少の無駄はありますが、スタイルにライブ変更を加えるなどの開発タスクは簡単です。
Xeoncross 14

2
コマンドの実行に2秒以上かかるとどうなりますか?
15

@thirtythreeforty Ubuntuでの簡単な実験では、コマンドの実行にどれだけ時間がかかっても、ウォッチは2秒間待機することが示されています。FWIWの場合、スリープ期間は「-n」で指定でき、最小0.1秒までです。
ジョナサンハートリー

5

WatchdogはPythonプロジェクトであり、まさにあなたが探しているものです。

サポートされているプラ​​ットフォーム

  • Linux 2.6(inotify)
  • Mac OS X(FSEvents、kqueue)
  • FreeBSD / BSD(kqueue)
  • Windows(I / O完了ポートを備えたReadDirectoryChangesW、ReadDirectoryChangesWワーカースレッド)
  • OSに依存しない(ディレクトリスナップショット用にディスクをポーリングし、定期的にそれらを比較します。遅く、推奨されません)

コマンドラインラッパーを作成しましたwatchdog_exec

実行例

現在のディレクトリ内のファイルとフォルダーを含むfsイベントecho $src $dstで、fsイベントが変更されていない限りpython $srcコマンドを実行し、コマンドを実行します。

python -m watchdog_exec . --execute echo --modified python

短い引数を使用し、イベントに「main .py」が含まれる場合にのみ実行するように制限する:

python -m watchdog_exec . -e echo -a echo -s __main__.py

編集:ウォッチドッグには、という公式のCLIがありますwatchmedoので、それも確認してください。


4

プログラムが何らかのログ/出力を生成する場合、スクリプトに依存するそのログ/出力のルールでMakefileを作成し、次のようなことを行うことができます

while true; do make -s my_target; sleep 1; done

あるいは、偽のターゲットを作成し、そのルールでスクリプトを呼び出して、偽のターゲットにタッチすることもできます(ただし、スクリプトに依存します)。


11
while sleep 1 ; do something ; doneは、やや優れていwhile true ; do something ; sleep 1 ; doneます。少なくとも、Ctrl + Cを押すと簡単に停止します。
デニルソンサマイア

スリープを解除するとビジーループが発生しますか(CPUが発熱し、ラップトップのバッテリー寿命が低下します)?
スティーブンルー

2
@StevenLu:いいえ、睡眠は忙しい待機ではありません。問題は、睡眠が体内にある場合、Control-Cが睡眠を中断し、ループが最初からやり直されることです。ループオーバーを開始する電力使用量はわずかです。ターミナルで自分で試してみてください。身体が眠っている場合、Control-Cを押して動作する必要があります。
ヤヌストロエルセン

右。私はそれを逃し、睡眠がループ状態としてまだ存在していることを見なかったと思います。その小さな調整はとても素晴らしいです。
スティーブンルー

4

2
これは、機能が満載された200行のBashスクリプトでstat、指定されたファイル名をポーリングmd5sumし、出力で実行さ れ、この値が変更された場合に指定されたコマンドを再実行します。Bashであるため、Bashプロンプトで入力した場合とまったく同じように、指定されたコマンドを実行するのに適していると思われます。(対照的に、ここで他の言語で書かれたソリューションのほとんどは、たとえばのようなシェルエイリアスを含むコマンドの実行に失敗しますll
ジョナサンハートリー

4

ジルの答えを改善しました。

このバージョンはinotifywait1回実行され、modifyその後イベント(例:)を監視します。これは、発生したすべてのイベントで再実行する必要inotifywait ありません

早くて速い!(大きなディレクトリを再帰的に監視する場合でも)

inotifywait --quiet --monitor --event modify FILE | while read; do
    # trim the trailing space from inotifywait output
    REPLY=${REPLY% }
    filename=${REPLY%% *}
    # do whatever you want with the $filename
done

これは、Linuxのみのユーザー向けのページのベストアンサーです。ループ内のものを「execute $ @」に置き換えると、ユーザーはこのスクリプトを呼び出して実行する独自のコマンドを渡すことができます。「。scriptname COMMAND」のようなものを使用してソースを指定すると、シェルエイリアスを含むコマンドでも動作します。これにより、PATH上のスクリプト名が引き続き検出されます。
ジョナサンハートリー

「返信を読んでいる間」と言うつもりですか?
ジョナサンハートリー

1
説明をありがとう。段階的廃止に感謝します!これらのコメントは削除しますが、もちろん今は削除しません。
ジョナサンハートリー

3

プログラミング側ではもう少しですが、inotifyのようなものが必要です。jnotifypyinotifyなど、多くの言語で実装されています。

このライブラリを使用すると、単一のファイルまたはディレクトリ全体を監視し、アクションが検出されたときにイベントを返すことができます。返される情報には、ファイル名、アクション(作成、変更、名前変更、削除)、ファイルパスなどの有用な情報が含まれます。


3

FreeBSDソリューションを探している人のために、ここにポートがあります:

/usr/ports/sysutils/wait_on

3

私はシンプルさが気に入ってwhile inotifywait ...; do ...; doneいますが、次の2つの問題があります。

  • 中に起こっているファイルの変更do ...;見逃されます
  • 再帰モードで使用すると遅い

そのため、これらの制限なしにinotifywaitを使用するヘルパースクリプトを作成しました:inotifyexec

のように、このスクリプトをパスに入れることをお勧めします~/bin/。使用法は、コマンドを実行するだけで説明されます。

例: inotifyexec "echo test" -r .


正規表現パターンマッチングをサポートするようにスクリプトを更新しました。
ワーナイト14年

両方の問題は、「-monitor」モードでinotifywaitを使用することで解決されます。cychoiの答えをご覧ください。
ジョナサンハートリー

3

改善されたセバスチャンのソリューションwatchコマンドを実行します。

watch_cmd.sh

#!/bin/bash
WATCH_COMMAND=${1}
COMMAND=${2}

while true; do
  watch -d -g "${WATCH_COMMAND}"
  ${COMMAND}
  sleep 1     # to allow break script by Ctrl+c
done

呼び出し例:

watch_cmd.sh "ls -lR /etc/nginx | grep .conf$" "sudo service nginx reload"

それは動作しますが、注意してください:watchコマンドには既知のバグがあります(manを参照):-g CMD出力のターミナル部分のVISIBLEでのみ変更に反応します。


2

あなたは反射を試すことができます。

Reflexは、ディレクトリを監視し、特定のファイルが変更されたときにコマンドを再実行する小さなツールです。compile / lint / testタスクを自動的に実行し、コードが変更されたときにアプリケーションをリロードするのに最適です。

# Rerun make whenever a .c file changes
reflex -r '\.c$' make

ツールについて少し引用/説明できますか?ガイダンスとしてソフトウェアを推奨する方法を簡単に読んでください。
ベルティエブ

1

ファイルの変更を追跡するために使用しているワンライナーの回答:

$ while true ; do NX=`stat -c %Z file` ; [[ $BF != $NX ]] && date >> ~/tmp/fchg && BF=$NX || sleep 2 ; done

最初の日付が開始時刻であることがわかっている場合、BFを初期化する必要はありません。

これはシンプルでポータブルです。ここにスクリプトを使用した同じ戦略に基づく別の答えがあります。こちらもご覧ください。


使用法:これを使用してデバッグし、監視し~/.kde/share/config/plasma-desktop-appletsrcます。何らかの未知の理由で私を失い続けることSwitchTabsOnHover=false


1

このスクリプトを使用して実行します。私はモニターモードでinotifyを使用しています

#!/bin/bash
MONDIR=$(dirname $1)
ARQ=$(basename $1)

inotifywait -mr -e close_write $MONDIR | while read base event file 
do
  if (echo $file |grep -i "$ARQ") ; then
    $1
  fi
done

これをrunatwrite.shとして保存します

Usage: runatwrite.sh myfile.sh

書き込みのたびにmyfile.shを実行します。


1

OS Xを使用している場合は、LaunchAgentを使用してパス/ファイルの変更を監視し、それが発生したときに何かを行うことができます。参考までに、LaunchControlは、デーモン/エージェントを簡単に作成/変更/削除するのに適したアプリです。

ここから取られた例

<?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>test</string>
    <key>ProgramArguments</key>
    <array>
        <string>say</string>
        <string>yy</string>
    </array>
    <key>WatchPaths</key>
    <array>
        <string>~/Desktop/</string>
    </array>
</dict>
</plist>


0

特定のファイルへの変更をグーグルで見つけた人にとっては、答えはもっと簡単です(Gillesの答えに触発されます)。

特定のファイルが書き込まれた後に何かをしたい場合は、次のようにします。

while true; do
  inotifywait -e modify /path/to/file
  # Do something *after* a write occurs, e.g. copy the file
  /bin/cp /path/to/file /new/path
done

たとえば、これcopy_myfile.shを名前を付けて.sh保存し、ファイルを/etc/init.d/フォルダーに入れて、起動時に実行します。


繰り返しごとにinotifywaitを実行するというGilesの答えと問題を共有します。これは、非常に大きなディレクトリを再帰的に監視する場合に応答しなくなる可能性があります。これに対する修正については、cychoiの回答を参照してください。
ジョナサンハートリー

0

「fido」ツールは、このニーズに対するもう1つのオプションです。https://www.joedog.org/fido-home/ご覧ください


ソフトウェアを推奨する方法については、ソフトウェアを推奨する方法をご覧ください。少なくともリンク、ソフトウェア自体に関する追加情報、および質問の問題を解決するためにそれをどのように使用できるかを提供する必要があります。
DavidPostill

0

いくつかの他の人が行ったように、私はこれを行うための軽量のコマンドラインツールも書きました。完全に文書化され、テストされ、モジュール化されています。

Watch-Do

設置

以下を使用してインストールできます(Python3とpipがある場合)。

pip3 install git+https://github.com/vimist/watch-do

使用法

次を実行して、すぐに使用します。

watch-do -w my_file -d 'echo %f changed'

機能の概要

  • ファイルグロビングをサポート(-w '*.py'またはを使用-w '**/*.py'
  • ファイルの変更に対して複数のコマンドを実行します(-dフラグを再度指定するだけです)
  • グロビングが使用されているかどうかを監視するためにファイルのリストを動的に維持します(-rこれをオンにするため)
  • ファイルを「見る」ための複数の方法:
    • 変更時刻(デフォルト)
    • ファイルハッシュ
    • 自分で実装するのは簡単です(これは、ModificationTimeウォッチャーです)
  • モジュール設計。コマンドを実行したい場合、ファイルにアクセスしたときに、独自のウォッチャー(実行者を実行するかどうかを決定するメカニズム)を作成するのは簡単です。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.