Skip to content

Comprehensive Guide to Monitoring File System Events with inotifywait

inotifywait is a C library and a set of command-line programs providing a simple interface to inotify.

Installation

emerge --ask inotify-tools

Introduction

The Linux inotify system provides a powerful mechanism to monitor file system events, allowing applications to watch for changes to files and directories. inotifywait, a command-line utility leveraging this system, offers a straightforward way to utilize these capabilities in scripts and command-line operations. This guide is designed to showcase a variety of use cases for inotifywait, from basic monitoring to complex file management tasks, making it an invaluable resource for developers, system administrators, and IT professionals seeking to enhance their toolkit.

Options

| EVENTS | | The following events are valid for use with the -e option | access | A watched file or a file within a watched directory was read from. | modify | A watched file or a file within a watched directory was written to. | attrib | The metadata of a watched file or a file within a watched directory was modified. This includes timestamps, file permissions, extended attributes etc. | close_write | A watched file or a file within a watched directory was closed, after being opened in writable mode. This does not necessarily imply the file was written to. | close_nowrite | A watched file or a file within a watched directory was closed, after being opened in read-only mode. | close | A watched file or a file within a watched directory was closed, regardless of how it was opened. Note that this is actually implemented simply by listening for both close_write and close_nowrite, hence all close events received will be output as one of these, not CLOSE. | open | A watched file or a file within a watched directory was opened. | moved_to | A file or directory was moved into a watched directory. This event occurs even if the file is simply moved from and to the same directory. | moved_from | A file or directory was moved from a watched directory. This event occurs even if the file is simply moved from and to the same directory. | move | A file or directory was moved from or to a watched directory. | move_self | A watched file or directory was moved. After this event, the file or directory is no longer being watched. | create | A file or directory was created within a watched directory. | delete | A file or directory within a watched directory was deleted. | delete_self | A watched file or directory was deleted. | unmount | The filesystem on which a watched file or directory resides was unmounted.

Additional Options

Monitor files that is edited/created/deleted/opened/closed in a dir

inotifywait -m -q -r \
  --format '%T % e %w%f' \
  --timefmt '%d/%m/%Y-%H:%M:%S%z' /mnt/usb/glftpd/ | \
   while IFS=' ' read -r time event file; do
    echo "file: $file"
  done

Notify file change

while inotifywait -q -e modify filename >/dev/null; do
    echo "filename is changed"
    # do whatever else you need to do
done

Monitor dir every minute

inotifywatch -v -e access -e open -e create -e modify -t 60 -r

Close write

while inotifywait -e close_write myfile.py; do ./myfile.sh; done

Monitor a single directory (non-recursive)

inotifywait -q -m -e create /path/to/directory

Exclude specific files or directories

inotifywait -q -m -r --exclude '(^\.git|node_modules)' /path/to/directory

!!! Example "Only monitor specific file types

inotifywait -q -m -r --include '\.txt$' /path/to/directory"

Display events as they occur

inotifywait -m -r -e create /path/to/directory

Scripts

Run rsync by notify timeĀ¶

cwd=$(pwd)

inotifywait -mr \
    --timefmt '%d/%m/%y %H:%M' --format '%T %w %f' \
    -e close_write /tmp/test |
    while read -r date time dir file; do
        changed_abs=${dir}${file}
        changed_rel=${changed_abs#"$cwd"/}

        rsync --progress --relative -vrae 'ssh -p 22' "$changed_rel" \
            usernam@example.com:/backup/root/dir && \
            echo "At ${time} on ${date}, file $changed_abs was backed up via rsync" >&2
        done

If filename exist and inotiwait notice a change run script

inotifywait -e close_write,moved_to,create -m . |
while read -r directory events filename; do
  if [ "$filename" = "myfile.py" ]; then
    ./myfile.py
  fi
done

Monitor file and print last line when file is modified

inotifywait -r -e modify -m . \
    | while read -r directory events filename; do  
        tail -n1 $filename; 
      done

Print filename that was modified, created, or closed

inotifywait -r -e close_write,moved_to,create,modify -m $LOGDIR |
while read -r directory events filename; do
    echo $filename
done

Trigger a command each time a file is created in a directory (inotify)

inotifywait -mrq -e CREATE format %w%f /path/to/dir | 
    while read FILE; do 
        chmod g=u "$FILE";
    done

Immediately put execute permission on any file saved/created in $HOME/bin

inotifywait -mr -e CREATE $HOME/bin/ | 
    while read i; do 
        chmod +x $(echo "$i" | sed 's/ \S* //'); 
    done

Debug how files are being accessed by a process

inotifywait -m -r .

Print last filename that has been modified

inotifywait -m --exclude "[^j].$|[^s]$" /path -e create -e moved_to |
    while read dir action file; do
        echo "The file '$file' appeared in directory '$dir' via '$action'"
    done
httpd-logs

A short shell script to efficiently wait for httpd-related log messages and do something appropriate

while ! inotifywait -e modify /var/log/messages; do
   if tail -n1 /var/log/messages | grep httpd; then
       kdialog --msgbox "Apache needs love!"
   fi
done

Custom format

inotifywait -m -r --format '%:e %f' ~/test

Enforce file permissions

inotifywait -qmr -e 'moved_to,create' --format '%w%f%0' --no-newline ~/test |\
while IFS= read -r -d '' file;do
   chmod -v a+rX "$file"
done

Block all brute-force attacks in realtime (IPv4/SSH)

inotifywait -r -q --format %w /var/log/auth.log \
    |grep -i "Failed pass" \
    |tail -n 1 \
    |grep -oE '\b([0-9]{1,3}\.){3}[0-9]{1,3}';
    iptables -I INPUT -i eth0 -s "$(cat /var/log/auth.log \
        |grep "authentication failure; l" \
        |awk -Frhost= '{print $2}' \
        |tail -n 1)" -j DROP

Notify when true

event=$(inotifywait --format '%e' /var/log) || exit
[ "$event" = "MODIFY" ] && echo 'file modified!' >&2
[ "$event" = "DELETE_SELF" ] && echo 'file deleted!' >&2

Monitor dir and if file extension match, remove metadata (example)"

inotifywait -m /path -e create -e moved_to |
    while read path action file; do
        if [[ "$file" =~ .*xml$ ]]; then # Does the file end with .xml?
            echo "xml file" # If so, do your thing here!
        fi
done

Print filename with full path for all newly created files

inotifywait -q -m -r -e create /home/wuseman/emagnet/websites/nohide.space/ |
  while read -r directory event filename; do
    if [[ $event == "CREATE" ]]; then
      echo "File created: $directory$filename"
    fi
  done

Print filename for all modified files

inotifywait -q -m -r -e modify /path/to/directory |
  while read -r directory event filename; do
    if [[ $event == "MODIFY" ]]; then
      echo "File modified: $filename"
    fi
  done

Execute a command on file creation

inotifywait -q -m -r -e create /path/to/directory |
  while read -r directory event filename; do
    if [[ $event == "CREATE" ]]; then
      # Replace the following line with your desired command
      command_to_execute "$filename"
    fi
  done

Print filename and timestamp for all modified files

inotifywait -q -m -r -e modify /path/to/directory |
  while read -r directory event filename; do
    if [[ $event == "MODIFY" ]]; then
      echo "File modified: $filename"
      echo "Timestamp: $(date +"%Y-%m-%d %H:%M:%S")"
    fi
  done

Perform an action on modified files

inotifywait -q -m -r -e modify /path/to/directory |
  while read -r directory event filename; do
    if [[ $event == "MODIFY" ]]; then
      # Replace the following line with your desired action
      echo "File modified: $filename"
      # Perform your action here
    fi
  done

Track specific file extensions

inotifywait -q -m -r -e modify --include '\.(txt|csv)$' /path/to/directory |
  while read -r directory event filename; do
    if [[ $event == "MODIFY" ]]; then
      echo "File modified: $filename"
    fi
  done

Print filename and size for all modified files

inotifywait -q -m -r -e modify --format '%f %s' /path/to/directory |
  while read -r filename size; do
    echo "File modified: $filename"
    echo "Size: $size bytes"
  done

Monitor file deletions

inotifywait -q -m -r -e delete /path/to/directory |
  while read -r directory event filename; do
    if [[ $event == "DELETE" ]]; then
      echo "File deleted: $filename"
    fi
  done

Track directory modifications

inotifywait -q -m -r -e modify --format '%w%f' /path/to/directory |
  while read -r modified_path; do
    echo "Directory modified: $modified_path"
  done

Exclude specific file types

inotifywait -q -m -r -e modify --exclude '\.(jpg|png)$' /path/to/directory |
  while read -r directory event filename; do
    if [[ $event == "MODIFY" ]]; then
      echo "File modified: $filename"
    fi
  done

Print filename and event type

inotifywait -q -m -r -e modify --format '%w%f %e' /path/to/directory |
  while read -r modified_path event_type; do
    echo "File modified: $modified_path"
    echo "Event type: $event_type"
  done

Print detailed information using JSON format

inotifywait -q -m -r -e modify --format '{"path": "%w%f", "event": "%e"}' /path/to/directory |
  while read -r json_data; do
    echo "Received event:"
    echo "$json_data"
    # Process the JSON data as needed
  done

Custom output format with additional information

inotifywait -q -m -r -e modify --format 'File: %w%f, Event: %e, Timestamp: %T' /path/to/directory |
  while read -r output; do
    echo "$output"
  done

!!! Example "To watch for created files and delete them if they are not of type .xt, you can use the following script:

```bash
inotifywait -q -m -r -e create --format '%w%f' /path/to/directory |
while read -r created_file; do
  if [[ ! $created_file =~ \.xt$ ]]; then
    echo "Deleting file: $created_file"
    rm "$created_file"
  fi
done
```

Watch multiple events

This command monitors the specified directory (/path/to/directory) for multiple events (create, modify, and delete). The -e option is used to specify the events to watch, separated by commas.

bash inotifywait -q -m -r -e create,modify,delete /path/to/directory