bash 如何在shell脚本中每2分钟查找目录中是否有新文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13264529/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 03:43:50  来源:igfitidea点击:

How to find if there are new files in a directory every 2 minutes in shell script?

bashshellunix

提问by user1452759

I have a directory called /home/user/local. Every two minutes or so, a new file is dumped into this directory. I need to check this directory every 2 minutes to see if a new file/files have landed in there. And if there are new files, I need to put a list of it into a variable to use later on. How do I do this shell script?

我有一个名为/home/user/local. 每两分钟左右,一个新文件被转储到这个目录中。我需要每 2 分钟检查一次此目录,以查看是否有新文件/文件落入其中。如果有新文件,我需要将它的列表放入一个变量中以供以后使用。我怎么做这个shell脚本?

回答by leafei

#! /usr/bin/env bash

FILELIST=/tmp/filelist
MONITOR_DIR=/home/usr/local

[[ -f ${FILELIST} ]] || ls ${MONITOR_DIR} > ${FILELIST}

while : ; do
    cur_files=$(ls ${MONITOR_DIR})
    diff <(cat ${FILELIST}) <(echo $cur_files) || \
         { echo "Alert: ${MONITOR_DIR} changed" ;
           # Overwrite file list with the new one.
           echo $cur_files > ${FILELIST} ;
         }

    echo "Waiting for changes."
    sleep $(expr 60 \* 2)
done

a quick & dirty way. :) It'll monitor the directory for changes, not only when there's new file dumped in, but also if some file is missing/deleted.

一种快速而肮脏的方式。:) 它将监视目录的更改,不仅在有新文件转储时,而且在某些文件丢失/删除时也会监视。

File list is stored in variable $cur_files.

文件列表存储在变量中$cur_files

回答by sampson-chen

inotifywaitis exactly what you are looking for: http://linux.die.net/man/1/inotifywait

inotifywait正是你要找的:http: //linux.die.net/man/1/inotifywait

回答by Ignacio Vazquez-Abrams

Set up a cron job that runs a script that takes the current listing and compares it to an older listing stored in a file somewhere.

设置一个运行脚本的 cron 作业,该脚本获取当前列表并将其与存储在某个文件中的旧列表进行比较。

回答by Rastislav Hasicek

Lets say your variable is called $listOF

假设您的变量名为 $listOF

Create a script:

创建脚本:

listOfFiles=`ls -t /home/user/local`
for i in $listOfFiles
do
echo "$listOF" | grep $i
if [[ "$?" -eq "0" ]]
then
listOF=$listOF" "$i
fi
done

And put this script into the crontab by cmd: crontab -e in format:

并通过cmd将这个脚本放入crontab中: crontab -e 格式:

1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59 * * * * <path to your script>

回答by S0AndS0

First off a big thank you to leafei, I'd hoped that it was that easy. However for my devices writing temporary files for loops wasn't portable enough for my current projectand I required performing actions for various things that might happen within a monitored directory, so here's the script I wrote based off leafei's answer and tested locally. Note formatting maybe off on first post...

首先非常感谢leafei,我希望这很容易。但是,对于我的设备,为循环编写临时文件对于我当前的项目来说不够便携,我需要对可能在受监控目录中发生的各种事情执行操作,所以这是我根据 Leafei 的答案编写并在本地测试的脚本。注意格式可能在第一次发布时关闭...

#!/usr/bin/env bash
Var_monitor_dir="${1?No directory passed}"
Var_sleep_time="${2:-120}"
Var_diff_opts="--suppress-common-lines"
Func_parse_change(){
    _added_input="$(grep -E ">" <<<"${@}")"
    _removed_input="$(grep -E "<" <<<"${@}")"
    if [ "${#_added_input}" != "0" ]; then
            mapfile -t _arr_added <<<"${_added_input}"
            let _added_count=0
            until [ "${#_arr_removed}" = "${_added_count}" ]; do
                _current_path="${_arr_removed[${_added_count}]}"
                if [ -f "${_current_path}" ]; then
                    echo "# ${0##*/} detected added file: ${_current_path}"
                elif [ -d "${_current_path}" ]; then
                    echo "# ${0##*/} detected added directory ${_current_path}"
                elif [ -p "${_current_path}" ]; then
                    echo "# ${0##*/} detected added named pipe ${_current_path}"
                fi
                ## Ignore other added input and add to index counter
                let _added_count++
            done
            unset _added_count
    fi
    if [ "${#_removed_input}" != "0" ]; then
            mapfile -t _arr_removed <<<"${_added_input}"
            let _removal_count=0
            until [ "${#_arr_removed}" = "${_removal_count}" ]; do
                echo "# Removal detected: ${_arr_removed[${_removal_count}]}"
                let _removal_count++
            done
    fi
 }
 Func_watch_dir(){
    _current_listing=""
    while [ -d "${Var_monitor_dir}" ]; then
         _new_listing="$(ls "${Var_monitor_dir}")"
         _diff_listing="$(diff ${Var_diff_opts} <(echo "${_current_listing}") <(echo "${_new_listing}"))"
        if [ "${#_diff_listing}}" != "0" ]; then
            Func_parse_change "${_diff_listing}"
        fi
        _current_listing="${_new_listing}"
        sleep ${Var_sleep_time}
    done
}
if [ "${#@}" != "0" ]; then
     Func_watch_dir
     exit 0
else
     echo "${0##*/} needs a directory to monitor"
     exit 1
if

Assuming the above is saved as monitor_directory.shand the directory to be monitored is /tmpthen opening one terminal and inputting monitor_directory "/tmp"(or monitor_directory.sh "/tmp" "10"to have faster updates between tests) will start the loop that checks for changes. Then opening a second terminal try inputting the following and waiting for the first terminal to update

假设上述内容另存为monitor_directory.sh并且要监视的目录/tmp打开一个终端并输入monitor_directory "/tmp"(或monitor_directory.sh "/tmp" "10"在测试之间进行更快的更新)将启动检查更改的循环。然后打开第二个终端尝试输入以下内容并等待第一个终端更新

mkdir -p /tmp/test_dir
touch /tmp/test.file

After the wait time is up the first terminal should report that a file and a directory has appeared, if you run the following and wait again it'll show removals too.

等待时间结束后,第一个终端应报告已出现文件和目录,如果您运行以下命令并再次等待,它也会显示删除。

rmdir /tmp/test_dir
rm /tmp/test.file

Hope this helps some.

希望这对一些人有所帮助。