inotifywait command not detecting files but folders it does - linux

Im trying to use inotifywait to detect every time a file or folder gets moved into a folder in realtime (eg. /root in the case)
I tried this, which does detect both folders and files, but this is for a created file, I want it for a moved file/folder.
inotifywait --monitor --format %f --event create /root
So then I use this, but using this only sees when a folder is moved in, when I move in a file nothing is shown... :(
inotifywait --monitor --format %f --event moved_to /root
Any idea what's going on?
PS, Im using Linux, Debian 5 (Lenny).

You can specify many events with inotify. In your case it seems you need something like :
inotifywait --monitor --format %f --event move --event create /root
It should works. If you need more, read carefully the man page :
-e <event>, --event <event>
Listen for specific event(s) only.
The events which can be listened for are listed in the EVENTS section.
This option can be specified more than once.
If omitted, all events are listened for.
[...]
EVENTS
The following events are valid for use with the -e option:
[...]
move A file or directory was moved from or to a watched directory.
Note that this is actually implemented simply by listening for both moved_to
and moved_from, hence all close events received will be output as one or both
of these, not MOVE.
create A file or directory was created within a watched directory.
It works for me with move / touch. Hope it helps ...

Related

How to hold or copy files at run time in CENTOS 7

I have a tool that converts COBOL files to C++.
When I run the command, it generates the.cpp file from the.cbl file but deletes it at run time.
It is not holding the files or not saving the file in the designated folder, despite the fact that I can see that the.cpp file is created but destroyed within seconds.
I'm using CentOS 7.
Can somebody tell me how to keep that.cpp file or copy it at runtime to a different location?
You can use inotifywait to monitor the directory, where the CPP files are created. Whenever a CREATE event occurs, you can link the file into a backup directory.
#! /bin/bash
test -d backup || mkdir backup
inotifywait --monitor --event CREATE --format %f . |
while read file; do
ln "$file" backup/"$file"
done

Read updates from continuously updated directory

I am writing a bash script that looks at each file in a directory and does some sort of action to it. It's supposed to look something like this (maybe?).
for file in "$dir"* ; do
something
done
Cool, right? The problem is, this directory is being updated frequently (with new files). There is no guarantee that, at some point, I will technically be done with all the files in the dir (therefore exiting the for-loop), but not actually done feeding the directory with extra files. There is no guarantee that I will never be done feeding the directory (well... take that with a grain of salt).
I do NOT want to process the same file more than once.
I was thinking of making a while loop that runs forever and keeps updating some file-list A, while making another file-list B that keeps track of all the files I already processed, and the first file in file-list A that is not in file-list B gets processed.
Is there a better method? Does this method even work? Thanks
Edit: Mandatory "I am bash newb"
#Barmar has a good suggestion. One way to handle this is using inotify to watch for new files. After installing the inotify-tools on your system, you can use the inotifywait command to feed new-file events into a loop.
You may start with something like:
inotifywait -m -e MOVED_TO,CLOSED_WRITE myfolder |
while read dir events file, do
echo "Processing file $file"
...do something with $dir/$file...
mv $dir/$file /some/place/for/processed/files
done
This inotifywait command will generate events for (a) files that are moved into the directory and (b) files that are closed after being opened for writing. This will generally get you what you want, but there are always corner cases that depend on your particular application.
The output of inotifywait looks something like:
tmp/work/ CLOSE_WRITE,CLOSE file1
tmp/work/ MOVED_TO file2

How to listen only to specific events in inotifywait?

Can someone explain why inotifywait still reports about opened files, when I have excluded open?
mkdir /tmp/a
inotifywait --exclude acess,attrib,close_write,close_nowrite,close,open,moved_to,moved_from,move,delete,delete_self,unmount -r -m /tmp/a/
touch /tmp/a/test
/tmp/a/ OPEN test
/tmp/a/ CLOSE_NOWRITE,CLOSE test
All I am interested in is if new files are made or current files are modified.
I use CentOS 7, if that changes anything.
The -e event (Listen for specific event(s) only) is different from the --exclude <pattern> which is meant for not processing any events whose filename matches the specified regular expression. Your actual command needed to be without open on the list of events to watch on. For e.g. if you are interested in only create and modify just do
inotifywait -rme create,modify /tmp/a/
inotifywait(1) - Linux man page

linux - watch a directory for new files, then run a script

I want to watch a directory in Ubuntu 14.04, and when a new file is created in this directory, run a script.
specifically I have security cameras that upload via FTP captured video when they detect motion. I want to run a script on this FTP server so when new files are created, they get mirrored (uploaded) to a cloud storage service immediately, which is done via a script I've already written.
I found iWatch which lets me do this (http://iwatch.sourceforge.net/index.html) - the problem I am having is that iwatch immediately kicks off the cloud upload script the instant the file is created in the FTP directory, even while the file is in progress of being uploaded still. This causes the cloud sync script to upload 0-byte files, useless to me.
I could add a 'wait' in the cloud upload script maybe but it seems hack-y and impossible to predict how long to wait as it depends on file size, network conditions etc.
Whats a better way to do this?
Although inotifywait was mentioned in comments, a complete solution might be useful to others. This seems to be working:
inotifywait -m -e close_write /tmp/upload/ | gawk '{print $1$3; fflush()}' | xargs -L 1 yourCommandHere
will run
yourCommandHere /tmp/upload/filename
when a newly uploaded file is closed
Notes:
inotifywait is part of apt package inotify-tools in Ubuntu. It uses the kernel inotify service to monitor file or directory events
-m option is monitor mode, outputs one line per event to stdout
-e close_write for file close events for files that were open for writing. File close events hopefully avoid receiving incomplete files.
/tmp/upload can be replaced with some other directory to monitor
the pipe to gawk reformats the inotifywait output lines to drop the 2nd column, which is a repeat of the event type. It combines the dirname in column 1 with the filename in column 3 to make a new line, which is flushed every line to defeat buffering and encourage immediate action by xargs
xargs takes a list of files and runs the given command for each file, appending the filename on the end of the command. -L 1 causes xargs to run after each line received on standard input.
You were close to solution there. You can watch many different events with iwatch - the one that interests you is close_write. Syntax:
iwatch -e close_write <directory_name>
This of course works only if file's closed when the writing's complete, which, while it's a sane assumption, it's not necessarily a true one (yet often is).
Here's another version of reacting to a filesystem event by making a POST request to a given URL.
#!/bin/bash
set -euo pipefail
cd "$(dirname "$0")"
watchRoot=$1
uri=$2
function post()
{
while read path action file; do
echo '{"Directory": "", "File": ""}' |
jq ".Directory |= \"$path\"" |
jq ".File |= \"$file\"" |
curl --data-binary #- -H 'Content-Type: application/json' -X POST $uri || continue
done
}
inotifywait -r -m -e close_write "$watchRoot" | post

Inotify dynamically index new folders

Say for example you had a shell script that utilises inotifywait in the following form
inotifywait -m -e create /home/user1/*/*
Essentially you are asking it to monitor all folders two levels under user1. I've noticed with inotify that it can not dynamically index new folders.
For example you have a file system like
/home
/user1
/a
/b
Then you run the inotifywait script, it will monitor actions on the 'b' folder.
If you were to then add a new folder 'c' under 'a' (same level as 'b'), inotify will not monitor actions on this folder. Anyone got a way of remedying this?
Go up a level and monitor that with the recursive switch.
inotifywait -r -m -e create /home/user1/*
I don't know what you are using this for, but for indefinite watching you might want to check out iwatch.

Resources