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?
问题:
回答1:
#! /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
.
回答2:
inotifywait
is exactly what you are looking for: http://linux.die.net/man/1/inotifywait
回答3:
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.
回答4:
Lets say your variable is called $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:
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>
回答5:
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 project and 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...
#!/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.sh
and the directory to be monitored is /tmp
then 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
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.