जब भी कोई फाइल बदलती है तो कमांड को कैसे निष्पादित करें?


434

जब भी कोई फाइल बदलती है, मैं कमांड निष्पादित करने का एक त्वरित और सरल तरीका चाहता हूं। मैं कुछ बहुत ही सरल चाहता हूं, कुछ मैं एक टर्मिनल पर चलना छोड़ दूंगा और इसे बंद कर दूंगा जब भी मैं उस फ़ाइल के साथ काम कर रहा हूं।

वर्तमान में, मैं इसका उपयोग कर रहा हूं:

while read; do ./myfile.py ; done

और फिर मुझे उस टर्मिनल पर जाने और प्रेस करने की आवश्यकता है Enter, जब भी मैं अपने संपादक पर उस फ़ाइल को सहेजता हूं। मैं कुछ इस तरह से चाहता हूं:

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

या किसी अन्य समाधान के रूप में आसान है।

BTW: मैं विम का उपयोग कर रहा हूं, और मुझे पता है कि मैं BufWrite पर कुछ चलाने के लिए एक ऑटोकॉमैंड जोड़ सकता हूं, लेकिन यह उस तरह का समाधान नहीं है जैसा मैं अब चाहता हूं।

अद्यतन: यदि संभव हो तो मैं कुछ सरल, त्यागने योग्य चाहता हूं। क्या अधिक है, मैं एक टर्मिनल में कुछ चलाना चाहता हूं क्योंकि मैं प्रोग्राम आउटपुट देखना चाहता हूं (मैं त्रुटि संदेश देखना चाहता हूं)।

उत्तरों के बारे में: आपके सभी उत्तरों के लिए धन्यवाद! वे सभी बहुत अच्छे हैं, और हर एक दूसरों से बहुत अलग दृष्टिकोण लेता है। चूंकि मुझे केवल एक को स्वीकार करने की आवश्यकता है, मैं उस एक को स्वीकार कर रहा हूं जो मैंने वास्तव में उपयोग किया है (यह सरल, त्वरित और आसानी से याद था), भले ही मैं जानता हूं कि यह सबसे सुरुचिपूर्ण नहीं है।


संभावित क्रॉस साइट डुप्लिकेट की डुप्लिकेट: stackoverflow.com/questions/2972765/… (हालांकि यहाँ यह विषय =) पर है)
Ciro Santilli 新疆 of of 六四

मैं एक क्रॉस साइट डुप्लिकेट से पहले संदर्भित किया गया है और इसे अस्वीकार कर दिया गया था: एस;)
फ्रांसिस्को तापिया

4
जोनाथन हार्टले द्वारा किया गया समाधान यहां अन्य समाधानों पर बनाता है और बड़ी समस्याओं को हल करता है जो शीर्ष-मतदान के जवाब हैं: कुछ संशोधनों को गायब करना और अक्षम होना। कृपया उनके लिए स्वीकृत उत्तर को बदल दें, जिसे github पर github.com/tartley/rerun2 (या उन दोषों के बिना किसी अन्य समाधान पर) में बनाए रखा जा रहा है
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से चल रहा है)। दूसरे स्निपेट में यह दोष नहीं है। हालाँकि, सावधान रहें कि यह मानता है कि फ़ाइल नाम में व्हॉट्सएप नहीं है। यदि यह समस्या है, --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 (एक उपकरण जो कई अन्य यूनिक्स वेरिएंट पर भी काम करता है, लिनक्स के प्रत्येक वेरिएंट के इनोटिफाई का उपयोग करके)।


46
मैंने एक सरल-से-उपयोग की गई sleep_until_modified.shस्क्रिप्ट में यह सब कुछ (कुछ बैश ट्रिक के साथ) समझाया है , जो उपलब्ध है: bitbucket.org/denilsonsa/small_scripts/src
Denilson Sá Maa

14
while sleep_until_modified.sh derivation.tex ; do latexmk -pdf derivation.tex ; doneशानदार है। धन्यवाद।
Rhys Ulerich

5
inotifywait -e delete_selfमेरे लिए अच्छा काम करने लगता है।
कोस

3
यह सरल है, लेकिन दो महत्वपूर्ण मुद्दे हैं: ईवेंट को याद किया जा सकता है (लूप में सभी ईवेंट) और इनोटिफ़ाइवाइट की आरंभीकरण हर बार किया जाता है जो इस समाधान को बड़े पुनरावर्ती फ़ोल्डरों के लिए धीमा बनाता है।
वर्नट

6
किसी कारण के लिए while inotifywait -e close_write myfile.py; do ./myfile.py; doneहमेशा कमांड (बैश और zsh) को चलाने के बिना बाहर निकलता है। इस काम के लिए मुझे जोड़ने की जरूरत थी || true, जैसे: while inotifywait -e close_write myfile.py || true; do ./myfile.py; done
ideasman42

166

entr ( http://entrproject.org/ ) एक बेहतर फ्रेंडली इंटरफ़ेस प्रदान करता है जिसे tootify (और * BSD & Mac OS X) भी सपोर्ट करता है।

यह देखने के लिए कई फ़ाइलों को निर्दिष्ट करने के लिए बहुत आसान बनाता है (केवल द्वारा सीमित ulimit -n), फ़ाइलों को प्रतिस्थापित किए जाने से निपटने के लिए परेशानी उठाता है, और कम बैश सिंटैक्स की आवश्यकता होती है:

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

मैं इसे अपने पूरे प्रोजेक्ट सोर्स ट्री पर उपयोग कर रहा हूं, जो मैं वर्तमान में संशोधित कर रहा हूं, उसके लिए यूनिट परीक्षण चलाने के लिए, और यह पहले से ही मेरे वर्कफ़्लो को भारी बढ़ावा दे रहा है।

जैसे झंडे -c(रन के बीच स्क्रीन को साफ़ करें) और -d(एक नई फ़ाइल को मॉनिटर की गई निर्देशिका में जोड़े जाने पर बाहर निकलें ) और भी अधिक लचीलापन जोड़ें, उदाहरण के लिए आप कर सकते हैं:

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

2018 की शुरुआत में यह अभी भी सक्रिय विकास में है और इसे डेबियन और उबंटू ( apt install entr) में पाया जा सकता है ; लेखक के रेपो से निर्माण किसी भी मामले में दर्द मुक्त था।


3
नई फ़ाइलों और उनके संशोधनों को संभालता नहीं है।
12

2
@Wernight - 7 मई 2014 को एनआरआर का नया -dझंडा है; यह थोड़ा अधिक लंबी घुमावदार है, लेकिन आप while sleep 1 ; do find . -name '*.py' | entr -d ./myfile.py ; doneनई फ़ाइलों से निपटने के लिए कर सकते हैं ।
पॉल फेनी

1
entr भी debian repos में debian jessie / 8.2 से कम से कम उपलब्ध है ...
पीटर वी। मॉर्क

5
सबसे अच्छा मैं सुनिश्चित करने के लिए ओएस एक्स पर पाया। Fswatch बहुत सारी कायरतापूर्ण घटनाओं को पकड़ लेता है और मैं यह पता लगाने का समय व्यतीत नहीं करता कि क्यों
dtc

5
यह ध्यान देने योग्य है कि लायक है entr Homebrew पर उपलब्ध है, तो brew install entrअपेक्षा के अनुरूप काम करेगा
jmarceli

108

मैंने पायथन प्रोग्राम लिखा था, इसे ठीक - ठीक करने के लिए जब-जब बुलाया गया

उपयोग सरल है:

when-changed FILE COMMAND...

या कई फाइलें देखने के लिए:

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

FILEएक निर्देशिका हो सकती है। साथ में पुन: देखें -r%fफ़ाइलनाम को कमांड में पास करने के लिए उपयोग करें ।


1
@ysangkok हाँ यह करता है, कोड के नवीनतम संस्करण में :)
जॉह

4
अब "पाइप-इंस्टॉल जब-बदले" से उपलब्ध है। अभी भी अच्छी तरह से काम करता है। धन्यवाद।
अल फ्लानगन

2
स्क्रीन को साफ़ करने के लिए सबसे पहले आप उपयोग कर सकते हैं when-changed FILE 'clear; COMMAND'
डेव जेम्स मिलर

1
यह उत्तर इतना बेहतर है क्योंकि मैं इसे विंडोज पर भी कर सकता हूं। और इस लड़के ने वास्तव में जवाब पाने के लिए एक कार्यक्रम लिखा था।
वोल्फपैक'08

4
सबके लिए अच्छी खबर है! when-changedअब क्रॉस-प्लेटफॉर्म है! नवीनतम 0.3.0 रिलीज की जाँच करें :)
जॉह

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संशोधित समय बेहतर नहीं होगा "जब भी कोई फ़ाइल बदलती है" उत्तर?
Xen2050

1
क्या प्रति सेकंड कई बार स्टेटस चल रहा होगा क्योंकि डिस्क में कई रीड्स होंगे? या fstat प्रणाली कॉल स्वचालित रूप से किसी भी तरह इन प्रतिक्रियाओं कैश कर देगा? जब भी मैं बदलाव करता हूँ, अपने c कोड को संकलित करने के लिए एक प्रकार की 'ग्रन्ट वॉच' लिखने का प्रयास कर रहा हूँ
Oskenso Kashi

यह अच्छा है यदि आप जानते हैं कि फ़ाइल नाम अग्रिम में देखा जाना है। बेहतर होगा कि फिल्म का नाम पटकथा के लिए पास किया जाए। बेहतर तब भी होगा जब आप कई फ़ाइलनामों को पास कर सकते हैं (उदाहरण के लिए। "mywatch * .py")। बेहतर अभी भी होगा अगर यह उप-फाइलों में फ़ाइलों पर पुनरावृत्ति भी कर सकता है, जो कुछ अन्य समाधान करते हैं।
जोनाथन हार्टले

5
बस किसी को भी भारी रीड के बारे में सोच रहे हैं, तो मैंने उबंटू 17.04 में 0.05 के स्लीप के साथ और vmstat -dडिस्क एक्सेस देखने के लिए इस स्क्रिप्ट का परीक्षण किया । ऐसा लगता है कि linux इस तरह की चीज़ों को
कैच करने में

"COMMAND" में टाइपो है, मैं ठीक करने की कोशिश कर रहा था, लेकिन SO का कहना है कि "एडिट 6 कैरेक्टर से कम नहीं होना चाहिए"
user337085

30

विम का उपयोग कर समाधान:

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

लेकिन मुझे यह समाधान नहीं चाहिए क्योंकि यह टाइप करने के लिए परेशान है, यह याद रखना थोड़ा मुश्किल है कि क्या टाइप करना है, वास्तव में, और इसके प्रभावों को पूर्ववत करना थोड़ा मुश्किल है (चलाने की आवश्यकता है :au! BufWritePost myfile.py)। इसके अलावा, यह समाधान Vim को तब तक ब्लॉक करता है जब तक कि कमांड ने निष्पादन समाप्त नहीं कर दिया।

मैंने इस समाधान को पूर्णता के लिए यहाँ जोड़ा है, क्योंकि यह अन्य लोगों की मदद कर सकता है।

प्रोग्राम आउटपुट को प्रदर्शित करने के लिए (और अपने संपादन प्रवाह को पूरी तरह से बाधित कर दें, क्योंकि आउटपुट कुछ सेकंड के लिए आपके संपादक पर लिख देगा, जब तक आप Enter दबाते हैं), :silentकमांड को हटा दें ।


1
यह काफी अच्छा हो सकता है जब entr(नीचे देखें) के साथ जोड़ दिया जाता है - बस वीम को एक डमी फाइल को छूएं जो एनटीआर देख रहा है, और एनटीआर को पृष्ठभूमि में बाकी काम करने दें ... या tmux send-keysयदि आप ऐसे वातावरण में होते हैं :)
पॉल फेनी

अच्छा! आप अपनी .vimrcफ़ाइल के लिए मैक्रो बना सकते हैं
ErichBSchulz

23

यदि आप npmस्थापित करने के लिए होते हैं , nodemonतो संभवतः आरंभ करने का सबसे आसान तरीका है, विशेष रूप से ओएस एक्स पर, जो कि जाहिरा तौर पर उपकरण को निष्क्रिय नहीं करता है। जब कोई फ़ोल्डर बदलता है तो यह कमांड चलाने का समर्थन करता है।


5
हालाँकि, यह केवल .js और। Coff फ़ाइलें देखता है।
zelk

6
वर्तमान संस्करण किसी भी आदेश का समर्थन करता है, उदाहरण के लिए: nodemon -x "bundle exec rspec" spec/models/model_spec.rb -w app/models -w spec/models
kek

1
काश मेरे पास और जानकारी होती, लेकिन ऑक्स में बदलावों को ट्रैक करने की एक विधि होती है, fsevents
ConstantineK

1
OS X पर आप एक कुंजी के साथ Launch Daemons का उपयोग कर सकते हैं WatchPathsजैसा कि मेरे लिंक में दिखाया गया है।
एडम जॉन्स

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"
एटले डे

3
यदि आप हर पल अपना समाधान देखते हैं, तो यह हमेशा के लिए काम करता है और केवल कुछ फ़ाइल में परिवर्तन होने पर ही MY_COMMAND चलाएं: watch -n1 "watch -d -t -g ls -lR && MY_COMMAND"
mnesarco

घड़ी का मेरा संस्करण (लिनक्स पर watch from procps-ng 3.3.10) अपने अंतराल के लिए फ्लोट सेकंड को स्वीकार करता है, इसलिए watch -n0.2 ...हर सेकंड के पांचवें को पोल करेगा। उन स्वस्थ उप-मिलीसेकंड यूनिट परीक्षणों के लिए अच्छा है।
जोनाथन हार्टले

15

rerun2( गीथूब पर ) फॉर्म की 10-लाइन बैश स्क्रिप्ट है:

#!/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

अपने पैठ पर 'रेरुन' के रूप में गितुब संस्करण को सहेजें, और इसका उपयोग करके आह्वान करें:

rerun COMMAND

हर बार यह चालू होता है कि आपके मौजूदा निर्देशिका (पुनरावर्ती) के भीतर एक फाइलसिस्टम संशोधित घटना है।

चीजें जो इसके बारे में पसंद कर सकती हैं:

  • यह inotify का उपयोग करता है, इसलिए मतदान की तुलना में अधिक उत्तरदायी है। हर बार जब आप 'सेव' को हिट करते हैं, तो उप-मिलीसेकंड यूनिट परीक्षण चलाने या ग्राफविज़ डॉट फ़ाइलों को प्रस्तुत करने के लिए शानदार।
  • क्योंकि यह बहुत तेज़ है, आपको केवल प्रदर्शन कारणों से बड़े उप-विभाजकों (जैसे कि नोड_मॉड्यूल्स) को अनदेखा करने के लिए कहने से परेशान होने की ज़रूरत नहीं है।
  • यह अतिरिक्त सुपर रिस्पॉन्सिव है, क्योंकि यह स्टार्टअप पर केवल एक बार इनोटिफ़ाइवाइट कहता है, इसे चलाने के बजाय, और हर पुनरावृत्ति पर घड़ियों की स्थापना की महंगी हिट को आवर्ती करता है।
  • यह बैश की सिर्फ 12 लाइनें है
  • क्योंकि यह बैश है, यह आपको आदेश देता है कि आप इसे ठीक उसी तरह से पास करें जैसे कि आपने उन्हें बैश प्रॉम्प्ट पर टाइप किया था। (संभवत: यह कम ठंडा है यदि आप दूसरे शेल का उपयोग करते हैं।)
  • यह उन घटनाओं को नहीं खोता है, जबकि COMMAND निष्पादित हो रहा है, इस पृष्ठ के अधिकांश अन्य समाधानों के विपरीत है।
  • पहली घटना पर, यह 0.15 सेकंड के लिए एक 'मृत अवधि' में प्रवेश करता है, जिसके दौरान अन्य घटनाओं को अनदेखा किया जाता है, इससे पहले COMMAND को एक बार ठीक से चलाया जाता है। ऐसा इसलिए है कि क्रिएट-राइट-मूव डांस के कारण होने वाली घटनाओं की हड़बड़ी जो Vi या Emacs करता है जब एक बफर को सहेजने से संभवतः धीमी गति से चलने वाले टेस्ट सूट के कई श्रमसाध्य निष्पादन नहीं होते हैं। कोई भी घटना जो तब होती है जब COMMAND निष्पादित होता है, को नजरअंदाज नहीं किया जाता है - वे एक दूसरी मृत अवधि और बाद में निष्पादन का कारण बनेंगे।

चीजें जो इसके बारे में नापसंद हो सकती हैं:

  • यह inotify का उपयोग करता है, इसलिए Linuxland के बाहर काम नहीं करेगा।
  • क्योंकि यह inotify का उपयोग करता है, यह अधिक से अधिक उपयोगकर्ता inotify घड़ियों की तुलना में अधिक फ़ाइलों वाली निर्देशिकाओं को देखने की कोशिश पर रोक देगा। डिफ़ॉल्ट रूप से, यह मेरे द्वारा उपयोग की जाने वाली विभिन्न मशीनों पर लगभग 5,000 से 8,000 के बीच सेट किया गया लगता है, लेकिन इसे बढ़ाना आसान है। Https://unix.stackexchange.com/questions/13751/kernel-inotify-watch-limot-cched/ देखें
  • यह बैश उपनाम वाले आदेशों को निष्पादित करने में विफल रहता है। मैं कसम खा सकता था कि यह काम करता था। सिद्धांत रूप में, क्योंकि यह बैश है, एक उपसमूह में COMMAND निष्पादित नहीं कर रहा है, मैं यह काम करने की उम्मीद करूंगा। अगर किसी को पता है कि यह क्यों नहीं है तो मुझे अच्छा लगेगा। इस पृष्ठ पर अन्य समाधानों में से कई ऐसे आदेशों को निष्पादित नहीं कर सकते हैं।
  • व्यक्तिगत रूप से मेरी इच्छा है कि मैं टर्मिनल में एक कुंजी हिट करने में सक्षम था, जो मैन्युअल रूप से COMMAND के अतिरिक्त निष्पादन का कारण बन रहा है। क्या मैं इसे किसी भी तरह जोड़ सकता हूँ, बस? एक समवर्ती चल रहा है 'जबकि पढ़ें -n1' लूप जिसे निष्पादन भी कहते हैं?
  • अभी मैंने टर्मिनल को साफ़ करने के लिए इसे कोडित किया है और प्रत्येक पुनरावृत्ति पर निष्पादित COMMAND को प्रिंट किया है। कुछ लोग इस तरह की चीजों को चालू करने के लिए कमांड-लाइन झंडे जोड़ना पसंद कर सकते हैं, लेकिन यह आकार और जटिलता को कई गुना बढ़ा देगा।

यह @ साइकोइज़ एवर का परिशोधन है।


2
मेरा मानना ​​है कि आपको "$@"इसके बजाय उपयोग करना चाहिए $@, ताकि रिक्त स्थान वाले तर्कों के साथ ठीक से काम कर सकें। लेकिन एक ही समय में आप उपयोग करते हैं eval, जो रेरन के उपयोगकर्ता को उद्धृत करते समय अतिरिक्त सावधानी बरतने के लिए मजबूर करता है।
डेनिलसन सा मैया सेप

धन्यवाद डेनिलसन। क्या आप इस बात का उदाहरण दे सकते हैं कि उद्धृत करने की आवश्यकता कहां है? मैं पिछले 24 घंटों से इसका उपयोग कर रहा हूं और अब तक रिक्त स्थान के साथ कोई समस्या नहीं देखी है, और न ही सावधानी से कुछ भी उद्धृत किया है - बस के रूप में आमंत्रित किया गया है rerun 'command'। क्या आप केवल यह कह रहे हैं कि यदि मैंने "$ @" का उपयोग किया है, तो उपयोगकर्ता rerun command(बिना उद्धरण के) के रूप में आह्वान कर सकता है, जो मेरे लिए उतना उपयोगी नहीं है: मैं आमतौर पर इसे पारित करने से पहले कमांड के किसी भी प्रसंस्करण को करने के लिए बैश नहीं करना चाहता। फिर से करना उदाहरण के लिए यदि कमांड में "इको $ मायवर" शामिल है, तो मैं प्रत्येक पुनरावृत्ति में myvar के नए मूल्यों को देखना चाहूंगा।
जोनाथन हार्टले

1
जैसे कुछ rerun foo "Some File"टूट सकता है। लेकिन जब से आप उपयोग कर रहे हैं eval, इसे फिर से लिखा जा सकता है rerun 'foo "Some File"। ध्यान दें कि कभी-कभी पथ विस्तार रिक्त स्थान का परिचय दे सकता है: rerun touch *.fooसंभवतः टूट जाएगा, और उपयोग करने rerun 'touch *.foo'से थोड़ा अलग शब्दार्थ होता है (पथ विस्तार केवल एक बार, या कई बार हो रहा है)।
डेनिलसन सा मैया

सहायता के लिए धन्यवाद। हां: rerun ls "some file"रिक्त स्थान के कारण टूट जाता है। rerun touch *.foo*आमतौर पर ठीक काम करता है, लेकिन अगर फ़ाइल नाम * .foo में रिक्त स्थान है तो विफल रहता है। मुझे यह देखने में मदद करने के लिए धन्यवाद कि कैसे rerun 'touch *.foo'अलग-अलग शब्दार्थ हैं, लेकिन मुझे संदेह है कि एकल उद्धरण के साथ संस्करण मैं चाहता हूं कि शब्दार्थ है: मैं फिर से पुनरावृत्ति के प्रत्येक पुनरावृत्ति चाहता हूं जैसे कि मैंने फिर से कमांड टाइप किया - इसलिए मैं प्रत्येक सेशन पर विस्तार करना चाहता हूं *.foo। मैं उनके प्रभावों की जाँच करने के लिए आपके सुझावों की कोशिश करूँगा ...
जोनाथन हार्टले

इस PR ( github.com/tartley/rerun2/pull/1 ) और अन्य पर अधिक चर्चा ।
जोनाथन हार्टले

12

यहाँ एक सरल शेल बॉर्न शेल स्क्रिप्ट है:

  1. दो तर्क देता है: निगरानी की जाने वाली फाइल और एक कमांड (यदि आवश्यक हो तो तर्कों के साथ)
  2. उस फ़ाइल की प्रतिलिपि बनाते हैं जिसे आप / tmp निर्देशिका में देख रहे हैं
  3. यह देखने के लिए कि क्या आप जिस फ़ाइल की निगरानी कर रहे हैं, वह कॉपी की तुलना में नई है या नहीं, यह देखने के लिए हर दो सेकंड में चेक करता है
  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 पर काम करता है। केवल पोर्टेबिलिटी का मुद्दा मैं सोच सकता हूं कि क्या कुछ अन्य यूनिक्स के पास मक्तम (1) कमांड नहीं है, लेकिन उस स्थिति में आप सिर्फ अस्थायी फ़ाइल नाम को हार्ड कोड कर सकते हैं।


9
मतदान एकमात्र पोर्टेबल तरीका है, लेकिन अधिकांश प्रणालियों में एक फ़ाइल परिवर्तन अधिसूचना तंत्र है (लिनक्स पर इनोटिफाई, फ्रीबीएसडी पर केक्यूयू, ...)। जब आप करते हैं $cmd, तो आपको एक गंभीर उद्धरण समस्या होती है , लेकिन सौभाग्य से यह आसानी से ठीक होने योग्य है: cmdचर को निष्पादित करें और निष्पादित करें "$@"। आपकी स्क्रिप्ट किसी बड़ी फ़ाइल की निगरानी के लिए उपयुक्त नहीं है, लेकिन इसे बदलकर तय किया जा सकता cpहै touch -r(आपको केवल दिनांक की आवश्यकता है, सामग्री की नहीं)। पोर्टेबिलिटी-वार, -ntपरीक्षण के लिए बैश, ksh या zsh की आवश्यकता होती है।
गिल्स २

8

इंक्रॉन पर एक नजर है । यह क्रोन के समान है, लेकिन समय के बजाय घटनाओं को कम करने में उपयोग करता है।


यह काम करने के लिए बनाया जा सकता है, लेकिन इस पृष्ठ पर अन्य समाधानों की तुलना में एक एनरॉन प्रविष्टि बनाना काफी गहन प्रक्रिया है।
जोनाथन हार्टले

6

NodeJs, fsmonitor के साथ एक और समाधान :

  1. इंस्टॉल करें I

    sudo npm install -g fsmonitor
    
  2. कमांड लाइन से (उदाहरण के लिए, मॉनिटर लॉग और "रिटेल" यदि एक लॉग फ़ाइल बदल जाती है)

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

साइड नोट: उदाहरण द्वारा हल किया जा सकता है tail -F -q *.log, मुझे लगता है।
वोल्कर सिएगेल

यह केवल एक उदाहरण देने के लिए था, टर्मिनल tail -fनहीं clear
एटिका

6

विशेष रूप से इस प्लगइन के साथ गार्ड में देखें:

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

आप अपने प्रोजेक्ट की डायरेक्टरी में किसी भी पैटर्न को देखने के लिए इसे सेट कर सकते हैं, और बदलाव होने पर कमांड निष्पादित कर सकते हैं। अच्छा मौका यहां तक ​​कि इसके लिए एक प्लगइन उपलब्ध है जो आप पहली बार में करने की कोशिश कर रहे हैं।


6

यदि आपने नोडमॉन स्थापित किया है, तो आप यह कर सकते हैं:

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

लिनक्स के तहत:

man watch

watch -n 2 your_command_to_run

हर 2 सेकंड में कमांड चलाएगा।

यदि आपकी कमांड को चलने में 2 सेकंड से अधिक समय लगता है, तो घड़ी तब तक इंतजार करेगी जब तक कि इसे फिर से करने से पहले ऐसा नहीं किया जाता।


यह बहुत आसान है, हालांकि कुछ हद तक बेकार है, यह विकास कार्यों के लिए आसान है जैसे शैलियों में लाइव परिवर्तन करना।
Xeoncross

2
क्या होता है जब कमांड को चलाने में दो सेकंड से अधिक समय लगता है?
तीसवें प्रहर

@thirtythreeforty उबंटू पर एक त्वरित प्रयोग से पता चलता है कि घड़ी पूरे दो सेकंड तक इंतजार करेगी, चाहे कितनी देर तक चलने में कमांड लगे। FWIW, नींद की अवधि को '-n' के साथ निर्दिष्ट किया जा सकता है, न्यूनतम 0.1 सेकंड तक।
जोनाथन हार्टले

5

वॉचडॉग एक पायथन प्रोजेक्ट है, और जैसा आप देख रहे हैं वैसा ही हो सकता है:

समर्थित मंच

  • लिनक्स 2.6 (inotify)
  • मैक ओएस एक्स (FSEvents, kqueue)
  • FreeBSD / BSD (kqueue)
  • Windows (I / O पूर्ण पोर्ट के साथ ReadDirectoryChangesW; ReadDirectoryChangesW कार्यकर्ता सूत्र)
  • ओएस-इंडिपेंडेंट (डायरेक्टरी स्नैपशॉट के लिए डिस्क को प्रदूषित करना और समय-समय पर उनकी तुलना करना; धीमी और अनुशंसित नहीं)

बस इसके लिए एक कमांड-लाइन रैपर लिखा है watchdog_exec:

उदाहरण चलता है

एफएस घटना में वर्तमान निर्देशिका में फ़ाइलों और फ़ोल्डरों को शामिल करते हुए, echo $src $dstकमांड चलाएं , जब तक कि यह एफएस घटना को संशोधित नहीं किया जाता है, तब python $srcकमांड चलाएं ।

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

छोटी बहस का उपयोग करना, और केवल घटनाओं को निष्पादित करने के लिए प्रतिबंधित करना जब घटनाओं में " मुख्य .py" शामिल हो:

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

संपादित करें: अभी-अभी वॉचडॉग को एक आधिकारिक सीएलआई कहा जाता है watchmedo, इसलिए इसे भी देखें।


4

यदि आपका प्रोग्राम किसी प्रकार की लॉग / आउटपुट उत्पन्न करता है, तो आप उस लॉग / आउटपुट के लिए एक नियम बना सकते हैं जो आपकी स्क्रिप्ट पर निर्भर करता है और कुछ ऐसा करता है

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 दबाने पर कम से कम यह आसानी से बंद हो जाता है।
डेनिलसन सा माया

क्या नींद को हटाने से एक व्यस्त लूप (सीपीयू गर्मी पैदा करने और लैपटॉप पर बैटरी जीवन को नुकसान पहुंचाएगा) का कारण होगा?
स्टीवन लू

2
@StevenLu: नहीं, नींद एक व्यस्त प्रतीक्षा नहीं है। समस्या यह है कि यदि नींद शरीर में है, तो नियंत्रण-सी नींद को मार देगा और लूप खत्म हो जाएगा। लूप ओवर शुरू करने की शक्ति का उपयोग नगण्य है। इसे टर्मिनल में स्वयं आज़माएँ। अगर आपको शरीर में नींद है, तो काम करने के लिए आपको कंट्रोल-सी को पकड़ना होगा।
Janus Troelsen

सही। मुझे लगता है कि मैंने इसे याद किया और यह नहीं देखा कि नींद अभी भी लूप की स्थिति के रूप में मौजूद है। वह छोटा सा ट्विक बहुत कमाल का है।
स्टीवन लू

4

2
यह एक फीचर-पैक 200 लाइन बैश स्क्रिप्ट है जो statदिए गए फ़ाइलनाम पर मतदान करता है, md5sumआउटपुट पर चलता है , और दिए गए कमांड को फिर से चलाता है यदि यह मान बदलता है। क्योंकि यह बैश है, मुझे संदेह है कि यह दिए गए कमांड को ठीक से चलाने का अच्छा काम करता है जैसे कि आपने इसे बैश प्रॉम्प्ट पर टाइप किया था। (इसके विपरीत, अन्य भाषाओं में लिखे गए अधिकांश समाधान यहां उन कमांडों को निष्पादित करने में विफल होंगे, जो उदाहरण के लिए, शेल उपनाम जैसे हैं ll)
जोनाथन हार्टले

4

गाइल्स के जवाब में सुधार हुआ ।

यह संस्करण inotifywaitएक बार चलता है और modifyइसके बाद (.eg:) घटनाओं की निगरानी करता है । इस तरह कि हर घटना का सामना करने पर फिर से निष्पादित करने की आवश्यकता 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

यह केवल लिनक्स उपयोगकर्ताओं के लिए पेज पर सबसे अच्छा जवाब है। लूप के अंदर के सामान को 'निष्पादित $ @' के साथ बदलें, और उपयोगकर्ता इस स्क्रिप्ट को चलाने के लिए अपने स्वयं के कमांड में पास कर सकता है। यहां तक ​​कि यह कमांड के साथ भी काम करता है जिसमें शेल उपनाम होते हैं यदि आप इसे स्रोत बनाते हैं, तो "स्क्रिप्टनाम कॉमैंड" जैसी किसी चीज़ का उपयोग करके। यह अभी भी PATH पर स्क्रिप्टनाम ढूंढेगा।
जोनाथन हार्टले

मुझे लगता है कि आपको 'REPLY पढ़ते समय' लगाने का मतलब है?
जोनाथन हार्टले

1
स्पष्टीकरण के लिए धन्यवाद। इसे चरणबद्ध करने के लिए अनथक! मैंने उन टिप्पणियों को हटा दिया होगा, लेकिन निश्चित रूप से अब मैं नहीं करूंगा।
जोनाथन हार्टले

3

प्रोग्रामिंग पक्ष पर थोड़ा और, लेकिन आप कुछ ऐसा चाहते हैं जैसे कि आबंटित हो । कई भाषाओं में कार्यान्वयन हैं, जैसे कि jnotify और pyinotify

यह लाइब्रेरी आपको एकल फ़ाइलों या संपूर्ण निर्देशिकाओं की निगरानी करने की अनुमति देती है, और जब कोई क्रिया खोज की जाती है, तो घटनाओं को लौटा देती है। दी गई जानकारी में फ़ाइल का नाम, कार्रवाई (निर्माण, संशोधित, नाम बदलना, हटाना) और फ़ाइल पथ, अन्य उपयोगी जानकारी शामिल है।


3

आप में से जो लोग FreeBSD समाधान की तलाश में हैं, उनके लिए यहां पोर्ट है:

/usr/ports/sysutils/wait_on

3

मुझे सरलता पसंद है while inotifywait ...; do ...; doneलेकिन इसके दो मुद्दे हैं:

  • चूक के दौरान हो रहे फ़ाइल परिवर्तन याद किएdo ...; जाएंगे
  • पुनरावर्ती मोड में उपयोग करते समय धीमा

इसके बाद मैंने एक सहायक स्क्रिप्ट बनाई जो उन सीमाओं के बिना inotifywait का उपयोग करती है : inotifyexec

मेरा सुझाव है कि आप इस स्क्रिप्ट को अपने पथ में रखें, जैसे ~/bin/। उपयोग केवल कमांड चलाने से वर्णित है।

उदाहरण: inotifyexec "echo test" -r .


रेगेक्स पैटर्न मिलान का समर्थन करने के लिए स्क्रिप्ट अपडेट किया गया।
12

दोनों समस्याओं को "--monitor" मोड में inotifywait का उपयोग करके हल किया गया है। देखिए सिकोई का जवाब
जोनाथन हार्टले

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कमांड ने बग्स को जाना है (आदमी देखें): यह -g CMDआउटपुट के टर्मिनल भागों में केवल VISIBLE में परिवर्तन पर प्रतिक्रिया करता है ।


2

तुम पलटा सकता है ।

रिफ्लेक्स एक निर्देशिका को देखने के लिए एक छोटा सा उपकरण है और कुछ फाइलों के बदलने पर एक कमांड को फिर से चालू करता है। यह स्वचालित रूप से संकलन / लिंट / परीक्षण कार्यों को चलाने और कोड बदलने पर अपने आवेदन को फिर से लोड करने के लिए बहुत अच्छा है।

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

क्या आप उपकरण के बारे में थोड़ा सा उद्धरण / व्याख्या कर सकते हैं? मार्गदर्शन के लिए सॉफ़्टवेयर की अनुशंसा करने का एक त्वरित तरीका पढ़ें ।
बर्टिब

1

एक oneliner जवाब है कि मैं एक फ़ाइल परिवर्तन पर नज़र रखने के लिए उपयोग कर रहा हूँ:

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

अगर आपको पता है कि पहली तारीख शुरू करने का समय है तो आपको बीएफ शुरू करने की जरूरत नहीं है।

यह सरल और पोर्टेबल है। यहां एक स्क्रिप्ट का उपयोग करके उसी रणनीति पर आधारित एक और उत्तर है। आप भी देख लीजिए।


उपयोग: मैं इसे डीबग करने और नज़र रखने के लिए उपयोग कर रहा हूं ~/.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 का उपयोग कर सकते हैं और ऐसा होने पर कुछ कर सकते हैं। FYI करें - 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

जो लोग किसी विशेष फ़ाइल में परिवर्तन के लिए Googling द्वारा इसे पाते हैं , उनके लिए उत्तर बहुत सरल है ( गाइल्स के उत्तर से प्रेरित है )।

यदि आप किसी विशेष फ़ाइल के लिखे जाने के बाद कुछ करना चाहते हैं , तो यहां बताया गया है:

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/फ़ोल्डर में डाल दें ताकि इसे स्टार्टअप पर चलाया जा सके।


गाइल्स के जवाब के साथ समस्या को साझा करता है कि यह प्रत्येक पुनरावृत्ति पर इनोटिफ़ाइवाइट चलाता है, जो बहुत बड़ी निर्देशिकाओं को पुन: देखने के लिए अनुत्तरदायी हो सकता है। इसे ठीक करने के लिए साइकोय का जवाब देखें।
जोनाथन हार्टले

0

इस आवश्यकता के लिए 'फ़िदो' उपकरण अभी तक एक और विकल्प हो सकता है। Https://www.joedog.org/fido-home/ देखें


कृपया पढ़ें कि मैं कुछ युक्तियों के लिए सॉफ्टवेयर की सिफारिश कैसे करूं कि आपको सॉफ्टवेयर की सिफारिश करने के बारे में कैसे जाना चाहिए। आपको कम से कम एक लिंक प्रदान करना चाहिए, सॉफ़्टवेयर के बारे में कुछ अतिरिक्त जानकारी और प्रश्न में समस्या को हल करने के लिए इसका उपयोग कैसे किया जा सकता है।
DavidPostill

0

जैसा कि कुछ अन्य लोगों ने किया है, मैंने ऐसा करने के लिए एक हल्का कमांड लाइन टूल भी लिखा है। यह पूरी तरह से प्रलेखित, परीक्षण और मॉड्यूलर है।

घड़ी-करो

स्थापना

आप इसे स्थापित कर सकते हैं (यदि आपके पास पायथन 3 और पाइप है) का उपयोग कर:

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

प्रयोग

इसे सीधे चलाकर उपयोग करें:

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

सुविधाएँ अवलोकन

  • फ़ाइल ग्लोबिंग का समर्थन करता है (उपयोग करें -w '*.py'या -w '**/*.py')
  • एक फ़ाइल परिवर्तन पर कई कमांड चलाएं (बस -dफिर से ध्वज निर्दिष्ट करें)
  • गतिशील रूप से अगर ग्लोबिंग का उपयोग किया जाता है ( -rयह चालू करने के लिए) देखने के लिए फ़ाइलों की सूची बनाए रखता है
  • एक फ़ाइल को "देखने" के कई तरीके:
    • संशोधन समय (डिफ़ॉल्ट)
    • फ़ाइल हैश
    • अपने खुद के लागू करने के लिए तुच्छ (यह संशोधन घड़ी देखने वाला है)
  • मॉड्यूलर डिजाइन। यदि आप कमांड चलाना चाहते हैं, जब कोई फ़ाइल एक्सेस की जाती है, तो अपने स्वयं के द्रष्टा को लिखना तुच्छ है (तंत्र जो निर्धारित करता है कि क्या कर्ता को चलाया जाना चाहिए)।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.