Programing

파일 또는 디렉토리가 변경 될 때 쉘 스크립트를 실행하는 방법은 무엇입니까?

lottogame 2020. 12. 9. 07:41
반응형

파일 또는 디렉토리가 변경 될 때 쉘 스크립트를 실행하는 방법은 무엇입니까?


특정 파일이나 디렉토리가 변경 될 때 쉘 스크립트를 실행하고 싶습니다.

어떻게 쉽게 할 수 있습니까?


inotify-tools를 사용하십시오 .


이 스크립트를 사용하여 디렉토리 트리의 변경 사항에 대해 빌드 스크립트를 실행합니다.

#!/bin/bash -eu
DIRECTORY_TO_OBSERVE="js"      # might want to change this
function block_for_change {
  inotifywait --recursive \
    --event modify,move,create,delete \
    $DIRECTORY_TO_OBSERVE
}
BUILD_SCRIPT=build.sh          # might want to change this too
function build {
  bash $BUILD_SCRIPT
}
build
while block_for_change; do
  build
done

용도 inotify-tools. 빌드를 트리거하는 항목을 사용자 정의하는 방법은 inotifywait 매뉴얼 페이지확인하십시오 .


당신은 시도 할 수 entr파일이 변경 될 때 임의의 명령을 실행하는 도구. 파일 예 :

$ ls -d * | entr sh -c 'make && make test'

또는:

$ ls *.css *.html | entr reload-browser Firefox

또는 Changed!파일 file.txt이 저장 될 때 인쇄 :

$ echo file.txt | entr echo Changed!

디렉토리의 경우를 사용 -d하지만 루프에서 사용해야합니다. 예 :

while true; do find path/ | entr -d echo Changed; done

또는:

while true; do ls path/* | entr -pd echo Changed; done

커널 파일 시스템 모니터 데몬 확인

http://freshmeat.net/projects/kfsmd/

방법은 다음과 같습니다.

http://www.linux.com/archive/feature/124903


이 스크립트는 어떻습니까? 'stat'명령을 사용하여 파일의 액세스 시간을 가져오고 액세스 시간이 변경 될 때마다 (파일에 액세스 할 때마다) 명령을 실행합니다.

#!/bin/bash

while true

do

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

   if [[ "$ATIME" != "$LTIME" ]]

   then

       echo "RUN COMMNAD"
       LTIME=$ATIME
   fi
   sleep 5
done

언급했듯이 inotify-tools는 아마도 최고의 아이디어 일 것입니다. 그러나 재미를 위해 프로그래밍하는 경우 tail -f를 신중하게 적용하여 해커 XP를 획득 할 수 있습니다 .


다른 옵션이 있습니다 : http://fileschanged.sourceforge.net/

특히 "디렉토리를 모니터링하고 새 파일이나 변경된 파일을 보관"하는 "예제 4"를 참조하십시오.


디버깅 목적으로 쉘 스크립트를 작성하고 저장시 실행되도록하려면 다음을 사용합니다.

#!/bin/bash
file="$1" # Name of file
command="${*:2}" # Command to run on change (takes rest of line)
t1="$(ls --full-time $file | awk '{ print $7 }')" # Get latest save time
while true
do
  t2="$(ls --full-time $file | awk '{ print $7 }')" # Compare to new save time
  if [ "$t1" != "$t2" ];then t1="$t2"; $command; fi # If different, run command
  sleep 0.5
done

다음으로 실행

run_on_save.sh myfile.sh ./myfile.sh arg1 arg2 arg3

편집 : 위의 Ubuntu 12.04에서 Mac OS의 경우 ls 행을 다음과 같이 변경하십시오.

"$(ls -lT $file | awk '{ print $8 }')"

~ / .bashrc에 다음을 추가하십시오.

function react() {
    if [ -z "$1" -o -z "$2" ]; then
        echo "Usage: react <[./]file-to-watch> <[./]action> <to> <take>"
    elif ! [ -r "$1" ]; then
        echo "Can't react to $1, permission denied"
    else
        TARGET="$1"; shift
        ACTION="$@"
        while sleep 1; do
            ATIME=$(stat -c %Z "$TARGET")
            if [[ "$ATIME" != "${LTIME:-}" ]]; then
                LTIME=$ATIME
                $ACTION
            fi
        done
    fi
}

inotifywait 당신을 만족시킬 수 있습니다.

다음은 이에 대한 일반적인 샘플입니다.

inotifywait -m /path -e create -e moved_to -e close_write | # -m is --monitor, -e is --event
    while read path action file; do
        if [[ "$file" =~ .*rst$ ]]; then             # if suffix is '.rst'
            echo ${path}${file} ': '${action}        # execute your command
            echo 'make html'
            make html
        fi
    done

Example of using inotifywait:

Suppose I want to run rails test every time I modify a relevant file.

1. Make a list of the relevant files you want to watch:

You could do it manually, but I find ack very helpful to make that list.

ack --type-add=rails:ext:rb,erb --rails -f > Inotifyfile

2. Ask inotifywait to do the job

while inotifywait --fromfile Inotifyfile; do rails test; done

That's it!

NOTE: In case you use Vagrant to run the code on a VM, you might find useful the mhallin/vagrant-notify-forwarder extension.

UPDATE: Even better, make an alias and get rid of the file:

alias rtest="while inotifywait $(ack --type-add=rails:ext:rb,erb --rails -f | tr \\n \ ); do rails test; done"

참고URL : https://stackoverflow.com/questions/4060212/how-to-run-a-shell-script-when-a-file-or-directory-changes

반응형