새 파일의 폴더를 모니터링하는 스크립트?


127

스크립트 를 사용하여 폴더에서 새 파일을 감지하는 방법은 무엇입니까? 폴더에서 파일을 생성하자마자 처리하고 싶습니다. 이것이 가능합니까 아니면 매분마다 새로운 파일을 확인 하는 으로 스크립트를 예약 해야합니까?


1
파일이 처리되면 폴더에서 파일을 제거 하시겠습니까?
ztank1013

답변:


151

inotifywait예를 들어을 사용 하는 것을 고려해야합니다 .

inotifywait -m /path -e create -e moved_to |
    while read path action file; do
        echo "The file '$file' appeared in directory '$path' via '$action'"
        # do something with the file
    done

우분투에서는 패키지 inotifywait로 제공됩니다 inotify-tools. 버전 3.13부터 (Ubuntu 12.04에서 현재) inotifywait는 -f 옵션없이 파일 이름을 포함합니다. 이전 버전은 강제해야 할 수도 있습니다. 주목 해야 할 것은 이벤트 필터링을 수행하는 가장 좋은 방법은 -e옵션 inotifywait입니다. 또한 read명령은 위치 출력을 여러 변수에 지정하여 사용하거나 무시하도록 선택할 수 있습니다. grep / sed / awk를 사용하여 출력을 사전 처리 할 필요가 없습니다.


1
큰! 는 inotifywait내가 원하는 그냥 뭐이었다.
ihatetoregister

2
이것을 업데이트하고 싶습니다. 이것을 달성하기 위해 awk가 필요하지 않습니다. '-e create'로 이벤트를 필터링하고 '-f % f'또는 '-f % w % f'를 사용하여 전체 경로를 수행하여 파일 이름 만 가져올 수 있습니다. 따라서 위 스크립트의 첫 번째 줄은 다음과 같습니다. inotifywait -m / path -f % w % f -e create |
Lugoues

2
@Lugoues 당신은 당신이 얻을 -f 사용하려고하면 지금 The '--filename' option no longer exists. The option it enabled in earlier versions of inotifywait is now turned on by default.그래서, 당신은 할 필요가 inotifywait -m /path -e create |나는 시도하고이 답변을 편집 할거야.
Bruno Bronosky

1
이제는라는 휴대용 도구도 있습니다 fswatch. 나는 그것을 쓰지 않았지만 오픈 소스이며 그것을 사용합니다.

1
@Wender inotfiywait는 트리거 될 때 한 줄에 3 개의 정보를 출력합니다. 'read'bash 내장은 입력 행을 읽고 세 가지 정보 각각을 변수에 지정합니다. 따라서 첫 번째 조각은 변수 경로에, 두 번째 조각은 작업에, 세 번째 조각은 파일에 할당됩니다. 해당 변수에 값을 할당하면 나중에 에코 라인에서와 같이 사용할 수 있습니다. 추가 정보 : tldp.org/LDP/Bash-Beginners-Guide/html/sect_08_02.html
Tim


24

방금 이것을 요리하고 검사 사이에 파일이 누락 될 가능성을 제외하고는 큰 문제가 없습니다.

while true
do
       touch  ./lastwatch
       sleep 10
       find /YOUR/WATCH/PATH -cnewer ./lastwatch -exec SOMECOMMAND {} \;
done

파일 처리에 시간이 오래 걸리지 않으면 새 파일을 놓치지 않아야합니다. 당신은 또한 활동을 배경으로 할 수 있습니다 ... 그것은 방탄은 아니지만 inotify와 같은 외부 도구없이 일부 목적을 제공합니다.


잘 잡았습니다. 파일 이름에서 공백을 지원하도록 약간 개선했습니다.
Michael Sacchi

물론. 갈 길이야 왜 내가 그 길로 내려 갔는지 잘 모르겠습니다. 나는 정기적으로 -exec를 사용합니다.
Michael Sacchi

실시간이 아닙니다. 실시간 최고입니다
Farhan

3
inotify사용할 수없는 경우 최상의 솔루션 입니다. -type f파일 만 필터링하기 위해 추가 합니다. 그렇지 않으면 폴더도 반환됩니다.
Xiao Peng-ZenUML.com

네- -f filename옵션이 훌륭합니다. 따라서 남은 유일한 질문은 재부팅 할 때 시작하는 방법입니다. 이것을 태양열 발전소와 함께 사용하여이 os.system("ssh me@mysystem ' ( touch /home/me/alarms/low24 ) '")파일을 만들면 마스터 컴퓨터가 espeak저전압 을 사용 하고 발표하게됩니다. 그것은 이미 나에게 이메일을 보내지 만 내 시스템은 이미 시간의 맨 위에 시간을 말하므로 나머지는 모두 있습니다. askubuntu.com/questions/977613/…
SDsolar

17

당신은 watch당신의 스크립트에서 사용할 수 있습니다

watch -n 0.1 ls <your_folder>

폴더를 모니터링하고 0.1 초마다 모든 것을 나열합니다

약점

실시간이 아니므로 파일이 0.1 초 이내에 생성 및 삭제 된 경우 작동하지 않으며 watch최소 0.1 초만 지원합니다.


그것이 바로 내가 기억하려고 한 것입니다! 고마워요 !!
Joabe Lucena

9

대상 폴더 ( isempty편의를 위해 전화 할 것입니다 )가 비어 있고 하나 이상의 파일이 드롭되기를 기다리고 있다고 가정합니다 .

다음 명령을 사용할 수 있습니다.

ls -1A isempty | wc -l

폴더가 여전히 비어 있는지 확인하기 위해 새 파일이 없으면 0을 반환 isempty하거나 폴더가 여전히 비어 있으면 0보다 큰 값을 반환합니다 (실제로는 숫자 폴더에있는 파일 수).

그것은 바보 같은 if / then 테스트가 나머지 작업을 수행 할 수 있다고 말했습니다.

if [ $(ls -1A isempty | wc -l) -gt 0 ] ; then do_something ; fi

물론 do_something함수는 isempty폴더 내에서 파일을 조작 한 다음 처리 후 폴더 자체에서 파일 을 제거해야합니다.

crontab에 다음과 같은 줄을 추가하면 1 분에 한 번씩 검사가 실행 do_something되고 폴더가 비어 있지 않은 경우 작업 이 트리거됩니다 .

* * * * *     if [ $(ls -1A isempty | wc -l) -gt 0 ] ; then do_something ; fi

이 솔루션은 마운트 된 원격 파일 시스템에 작동합니다. inotify-tools 개발자가 퓨즈 작업을하고 있거나 2014 년 중반에있었습니다.
Rondo

3
ls스크립팅에 사용해서는 안됩니다 . find대신 사용 하거나 간단한 글러브
andsens

6

새 파일을 감지하려면 해당 파일을 처리하고 마지막에 진행된 파일을 삭제하면 systemd.path 를 사용할 수 있습니다 . 이 방법은 inotify를 기반으로합니다. DirectoryNotEmpty 옵션이 있으므로 systemd는 디렉토리의 파일을 감지 할 때 항상 스크립트를 실행할 수 있습니다. 진행된 파일을 삭제할 수 있고 스크립트가 디렉토리를 비워 둔 경우에만 작동한다는 것을 기억해야합니다.

먼저 mymonitor.service 파일을 준비하십시오.

[Unit]
Description=Start the script

[Service]
Type=oneshot
ExecStart=/path/to/your/script

다음으로 mymonitor.path로 이동하여 경로를 정의하십시오.

[Unit]
Description= Triggers the service

[Path]
DirectoryNotEmpty=/path/to/monitor

[Install]
WantedBy=multi-user.target

.path 파일 이름이 서비스 이름과 동일하면 .path 파일에 서비스 이름을 지정할 필요가 없습니다.

더미에 대한 파일 액세스 모니터링을 기반으로합니다.


4

entr

사용하는 entr것이 새로운 방법입니다 (크로스 플랫폼). 참고 entr는 폴링을 사용하지 않으므로 많은 대안에 비해 큰 이점이 있습니다.

폴링을 사용 kqueue(2)하거나 inotify(7)피합니다. entr빠른 피드백과 자동 테스트를 자연스럽고 완전히 평범하게하도록 작성되었습니다.

BSD에서는 pledge(2)

당신은 그것을 설치할 수 있습니다

apt-get install entr
dnf install entr

다음을 사용하여 새로 추가 한 디렉토리를 추적 할 수 있습니다.

while $(true); do
  # echo ./my_watch_dir | entr -dnr echo "Running trigger..."
  echo ./my_watch_dir | entr -dnr ##MY COMMAND##
done;

옵션은 (문서에서),

  • -d 입력으로 제공된 일반 파일의 디렉토리를 추적하고 새 파일이 추가되면 종료하십시오. 이 옵션을 사용하면 디렉토리를 명시 적으로 지정할 수도 있습니다. 이름이 '.'로 시작하는 파일 무시됩니다.
  • -n비 대화식 모드에서 실행하십시오. 이 모드에서 entr은 TTY를 읽거나 속성을 변경하지 않습니다.
  • -r 지속적 하위 프로세스를 다시로드하십시오. 표준 작동 모드와 마찬가지로 종료되는 유틸리티는 파일 시스템 또는 키보드 이벤트가 처리 될 때까지 다시 실행되지 않습니다. SIGTERM유틸리티를 다시 시작하기 전에 종료하는 데 사용됩니다. 쉘 스크립트가 신호를 마스킹하지 못하도록 프로세스 그룹이 작성됩니다. entr소켓과 같은 자원이 닫혔는지 확인하기 위해 유틸리티가 종료 될 때까지 기다립니다. TTY 제어는 하위 프로세스로 전송되지 않습니다.

2

배쉬는 이것을 쉽게 할 수 없습니다. 기본적으로 폴더의 모든 파일 목록을 가져와 주기적으로 새 목록을 가져 와서 비교하여 변경된 내용을 확인해야합니다.

당신이 찾고있는 것을 inotify라고합니다. 그것은 리눅스 커널에 내장되어 있으며 기본적으로 inotify가 돌아와서 foobar라는 새로운 파일이 있다고 지적하는 무언가가 일어나기를 기다리고 있습니다.

원하는 것을 달성하려면 perl과 같은 것으로 전환하고 Linux :: Inotify2를 사용해야합니다 (파이썬은 inotify도 지원하지만, 나는 perl 사람입니다).


0

이것은 cygwin과 Linux에서 작동합니다. 파일을 작성하는 이전 솔루션 중 일부는 디스크를 손상시킵니다. 이 scipt에는 그 문제가 없습니다 :

SIG=1
SIG0=$SIG
while [ $SIG != 0 ] ; do
 while [ $SIG = $SIG0 ] ; do
   SIG=`ls -1 | md5sum | cut -c1-32`
   sleep 10
 done
 SIG0=$SIG
 ls -lrt | tail -n 1
done

0

다음에 예를의 축약 버전 에 유래 특정 디렉토리의 모니터링을 필요로 내 프로젝트 중 하나에 테스트와 통합했습니다.

Var_dir="${1:-/tmp}"
Var_diff_sleep="${2:-120}"
Var_diff_opts="--suppress-common-lines"
Func_parse_diff(){
    _added="$(grep -E '>' <<<"${@}")"
    if [ "${#_added}" != "0" ]; then
        mapfile -t _added_list <<<"${_added//> /}"
        _let _index=0
        until [ "${#_added_list[@]}" = "${_index}" ]; do
            _path_to_check="${Var_dir}/${_added_list[${_index}]}"
            if [ -f "${_path_to_check}" ]; then
                echo "# File: ${_path_to_check}"
            elif [ -d "${_path_to_check}" ]; then
                echo "# Directory: ${_path_to_check}"
            if [ -p "${_path_to_check}" ]; then
                echo "# Pipe: ${_path_to_check}"
            fi
            let _index++
        done
        unset _index
    fi
}
Func_watch_bulk_dir(){
    _current_listing=""
    while [ -d "${Var_dir}" ]; do
        _new_listing="$(ls "${Var_dir}")"
        _diff_listing="$(diff ${Var_dec_diff_opts} <(${Var_echo} "${_current_listing}") <(${Var_echo} "${_new_listing}"))"
        if [ "${_diff_listing}" != "0" ]; then
            Func_parse_diff "${_diff_listing}"
        fi
        _current_listing="${_new_listing}"
        sleep ${Var_diff_sleep}
    done
}

다음 은 sshfs 마운트 지점에있는 파일이나 디렉토리를 자동으로 해독하기 위해 수정 된 버전의 스크립트 를 사용 하는 스크립트에 대한 링크입니다 . 앞서 언급 한 프로젝트.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.