Working with the File System

Watching for Directory Changes using std::filesystem

Can I watch a directory for changes using std::filesystem?

Abstract art representing computer programming

std::filesystem does not provide built-in support for watching a directory for changes. To achieve this, you need to use platform-specific APIs or third-party libraries.

On Windows, you can use the ReadDirectoryChangesW() function to watch for directory changes. Here’s a basic example using Windows API:

#include <windows.h>

#include <iostream>

void watch_directory(
  const std::wstring &directory) {
  HANDLE dir_handle = CreateFileW(
    directory.c_str(),
    FILE_LIST_DIRECTORY,
    FILE_SHARE_READ | FILE_SHARE_WRITE
      | FILE_SHARE_DELETE,
    nullptr,
    OPEN_EXISTING,
    FILE_FLAG_BACKUP_SEMANTICS,
    nullptr)
    ;

  if (dir_handle == INVALID_HANDLE_VALUE) {
    std::cerr << "Failed to open directory\n";
    return;
  }

  char buffer[1024];
  DWORD bytes_returned;

  while (true) {
    if (ReadDirectoryChangesW(
      dir_handle, buffer, sizeof(buffer), TRUE,
      FILE_NOTIFY_CHANGE_FILE_NAME
      | FILE_NOTIFY_CHANGE_DIR_NAME
      | FILE_NOTIFY_CHANGE_ATTRIBUTES
      | FILE_NOTIFY_CHANGE_SIZE
      | FILE_NOTIFY_CHANGE_LAST_WRITE
      | FILE_NOTIFY_CHANGE_LAST_ACCESS
      | FILE_NOTIFY_CHANGE_CREATION
      | FILE_NOTIFY_CHANGE_SECURITY,
      &bytes_returned,
      nullptr,
      nullptr
    )) {
      FILE_NOTIFY_INFORMATION *info =
        reinterpret_cast<
          FILE_NOTIFY_INFORMATION *>(buffer);
      std::wcout << "Change detected in: "
        << info->FileName << '\n';
    } else {
      std::cerr
        << "Failed to read directory changes\n";
    }
  }

  CloseHandle(dir_handle);
}

int main() {
  watch_directory(L"c:\\test");  
}
Change detected in: newfile.txt

In this example:

  • CreateFile opens the directory for monitoring.
  • ReadDirectoryChangesW watches for changes in the directory and reports them.
  • We print the name of the file that changed whenever a change is detected.

On Linux, you can use the inotify API to watch for directory changes. Here’s a basic example using inotify:

#include <limits.h>
#include <sys/inotify.h>
#include <unistd.h>

#include <iostream>

void watch_directory(const std::string &directory) {
  int inotify_fd = inotify_init();
  if (inotify_fd < 0) {
    std::cerr << "Failed to initialize inotify\n";
    return;
  }

  int watch_fd = inotify_add_watch(
    inotify_fd, directory.c_str(),
    IN_MODIFY | IN_CREATE | IN_DELETE
  );

  if (watch_fd < 0) {
    std::cerr << "Failed to add watch\n";
    close(inotify_fd);
    return;
  }

  char buffer[
    sizeof(struct inotify_event) + NAME_MAX + 1];

  while (true) {
    int length = read(
      inotify_fd, buffer, sizeof(buffer));
    if (length < 0) {
      std::cerr << "Failed to read inotify events\n";
      break;
    }

    struct inotify_event *event = reinterpret_cast<
      struct inotify_event *>(buffer);
    if (event->len) {
      std::cout << "Change detected in: "
        << event->name << '\n';
    }
  }

  inotify_rm_watch(inotify_fd, watch_fd);
  close(inotify_fd);
}

int main() {
  watch_directory("/tmp/test");
}
Change detected in: newfile.txt

In this example:

  • inotify_init initializes the inotify instance.
  • inotify_add_watch adds a watch on the specified directory.
  • read retrieves events, and we print the name of the file that changed.

These examples show how to watch directories on different platforms. Using a cross-platform library like boost::asio or libuv can simplify this process by providing a consistent API across multiple operating systems.

Answers to questions are automatically generated and may not have been reviewed.

A computer programmer
Part of the course:

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Free, unlimited access

This course includes:

  • 124 Lessons
  • 550+ Code Samples
  • 96% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved