Як виявити нові файли в папці зі скриптом bash ? Я хотів би обробити файли, як тільки вони створені в папці. Чи можливо це зробити чи мені потрібно запланувати скрипт із кроном, який щохвилини перевіряє наявність нових файлів?
Як виявити нові файли в папці зі скриптом bash ? Я хотів би обробити файли, як тільки вони створені в папці. Чи можливо це зробити чи мені потрібно запланувати скрипт із кроном, який щохвилини перевіряє наявність нових файлів?
Відповіді:
Слід розглянути можливість використання 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
У Ubuntu inotifywaitпередбачено inotify-toolsпакетом. З версії 3.13 (поточна в Ubuntu 12.04) inotifywaitбуде містити ім'я файлу без параметра -f. Старіші версії, можливо, знадобляться. Важливо зазначити, що -eваріант до inotifywait- це найкращий спосіб фільтрації подій. Крім того, ваша readкоманда може призначити позиційний вихід у декілька змінних, які ви можете використовувати або ігнорувати. Не потрібно використовувати grep / sed / awk для попередньої обробки виводу.
inotifywaitбуло саме те, що я хотів.
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 |я спробую відредагувати цю відповідь.
fswatch. Я його не писав, але це відкритий код і я його використовую.
Я вважаю за краще incron, так як це простіше в управлінні. По суті, це сервіс, який використовує inotifyі ви можете налаштувати конфігурації, щоб вжити заходів на основі операцій із зміни файлів.
Наприклад:
<directory> <file change mask> <command or action> options
/var/www/html IN_CREATE /root/scripts/backup.sh
Повний приклад ви можете побачити тут: http://www.cyberciti.biz/faq/linux-inotify-examples-to-replicate-directories/
Я щойно підготував це, і не бачу з цим величезних проблем, окрім крихітного шансу пропустити файли між чеками.
while true
do
touch ./lastwatch
sleep 10
find /YOUR/WATCH/PATH -cnewer ./lastwatch -exec SOMECOMMAND {} \;
done
Якщо обробка вашого файлу не займе багато часу, ви не повинні пропустити жоден новий файл. Ви також можете переглядати діяльність ... Це не куленепробивна, але вона виконує деякі цілі без зовнішніх інструментів, таких як ініціація.
inotifyйого немає. Я хотів би додати лише -type fдля фільтрування файлів. Інакше папка також буде повернута.
-f filenameваріант чудовий. Тоді єдине питання, що залишається - як це почати після перезавантаження. Я збираюся використовувати це зі своєю сонячною установкою, щоб os.system("ssh me@mysystem ' ( touch /home/me/alarms/low24 ) '")тоді створення цього файлу призвело до використання головним комп'ютером espeakі оголосить про низьку напругу. Він вже надсилає мені електронний лист, але оскільки моя система вже говорить про час у верхній частині години, у нього є все інше. askubuntu.com/questions/977613/…
Ви можете використовувати watchу своєму сценарії
watch -n 0.1 ls <your_folder>
Переглядає вашу папку і перераховує все, що в ній, кожні 0,1 секунди
Недолік
Це не в режимі реального часу, тому якщо файл був створений та видалений менш ніж за 0,1 секунди, це не працює, watchпідтримує лише 0,1 секунди.
Я припускаю, що цільова папка (я буду називати це isemptyпросто для зручності) порожня, і ви чекаєте, коли один або кілька файлів будуть видалені туди.
Можна використовувати таку команду:
ls -1A isempty | wc -l
просто перевірити, чи папка ще порожня, насправді вона поверне 0, якщо нового файлу немає (значить, isemptyпапка ще порожня), або, з іншого боку, поверне значення, що перевищує 0 (фактично число файлів, які зараз знаходяться в папці).
Це сказало нерозумно, якщо тест може зробити решту роботи:
if [ $(ls -1A isempty | wc -l) -gt 0 ] ; then do_something ; fi
Звичайно, do_somethingфункція повинна буде маніпулювати файлами (файлами) всередині isemptyпапки, а потім видаляти їх (їх) із самої папки після обробки.
Якщо ви додасте такий рядок у свій crontab, ви зможете запускати перевірку один раз на хвилину та запустити do_somethingдію, якщо папка, звичайно, не порожня:
* * * * * if [ $(ls -1A isempty | wc -l) -gt 0 ] ; then do_something ; fi
Якщо ви хочете виявити нові файли, то обробіть їх і в кінці видаліть файли, що дійшли, ви можете використовувати systemd.path . Цей метод заснований на інотифікації. Існує параметр 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.
Він заснований на моніторингу доступу до файлів чайників
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Запуск у неінтерактивному режимі. У цьому режимі записувач не намагається прочитати з TTY або змінити його властивості.-rПерезавантажте стійкий дочірні процес. Як і у стандартному режимі роботи, утиліта, яка закінчується, не виконується знову, поки не буде оброблена подія файлової системи або клавіатури.SIGTERMвикористовується для припинення утиліти до її перезапуску. Група процесів створюється для запобігання скриптам оболонки від маскування сигналів.entrчекає, поки утиліта вийде, щоб забезпечити закриття таких ресурсів, як сокети. Контроль TTY не передається дочірньому процесу.
Bash не може це зробити легко. Потрібно в основному отримати список усіх файлів у папці та періодично отримувати новий список і порівнювати їх, щоб побачити, що змінилося.
Те, що ви шукаєте, називається inotify. Його вбудовано в ядро Linux, і ви можете сидіти там, чекаючи, коли щось станеться, і після цього inotify повернеться і каже: "ей, є новий файл під назвою foobar"
Щоб здійснити те, що ви хочете, вам доведеться перейти на щось на кшталт perl і використовувати Linux :: Inotify2 (python, мабуть, підтримує ініціативу, але я - людина перл).
Це працює в cygwin та Linux. Деякі з попередніх рішень, які записують файл, призведуть до злому диска. У цього науковця немає такої проблеми:
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
Нижче наведена скорочена версія прикладу для stackoverflow, яку я перевірив та включив до одного з моїх проектів, який вимагає моніторингу конкретних каталогів.
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; вищезгаданий проект.