Отслеживание конкретного файла
С помощью inotify
можно мониторить не только папки, но и просто файлы. Для этого создавая watch_fd, просто укажите полный путь к файлу
int watch_fd = inotify_add_watch(inotify_fd, "/home/m/file.txt", IN_MODIFY);
в этом случае, при событии, у вас уже не будет имени файла event->name, но вы можете проверить, о каком файле пришло событие изменения сравнив event->wd
с watch_fd
Если они совпали значит событие пришло о файле который мониторится с помощью watch_fd
int length = read(inotify_fd, buffer, EVENT_BUF_LEN);
int i = 0;
while (i < length)
{
struct inotify_event *event = (struct inotify_event *)&buffer[i];
if (event->mask & IN_MODIFY && event->wd == watch_fd) {
cout << "файл изменился" << endl;
}
}
Отключение события отслеживания
Иногда может возникнуть необходимость отключать мониторинг файла или папки, в этом случае вам достаточно вызывать функцию
inotify_rm_watch(inotify_fd, watch_fd);
если же захотите включать отслеживание обратно, то просто еще раз вызовите
watch_fd = inotify_add_watch(inotify_fd, "/home/m/file.txt", IN_MODIFY);
Вызов bash команды из C++ и перехват вывода
Часто есть необходимость выполнить bash команду и вывод этой команды использовать в своей программе.
На самом деле это не очень сложно сделать. Вот вам функция, которая запускает команду cmd
и выдает в ответ строку содержащую результат работы команды.
std::string exec(string cmd) {
std::array<char, 128> buffer; // буфер для перехвата вывода команды
std::string result; // переменная в которой будет хранится итоговый полный вывод команды
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose); // создаем процесс
if (!pipe) {
throw std::runtime_error("popen() failed!");
}
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { // и пока команда генерит текст
result += buffer.data(); // подклеиваем его к нашей переменной result
}
return result;
}
Как ее использовать?
Например, хочу я запустить ls, тогда мне надо будет написать так
#include <iostream>
#include <sys/inotify.h>
#include <unistd.h>
#include <array> // добавил для работы с буффером
#include <memory> // добавил для работы с процессами
using namespace std;
// это скопипастил
std::string exec(string cmd) {
std::array<char, 128> buffer; // буфер для перехвата вывода команды
std::string result; // переменная в которой будет хранится итоговый полный вывод команды
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose); // создаем процесс
if (!pipe) {
throw std::runtime_error("popen() failed!");
}
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { // и пока команда генерит текст
result += buffer.data(); // подклеиваем его к нашей переменной result
}
return result;
}
int main(int argc, char* argv[]) {
string result = exec("ls -la ."); // вызываем нашу функцию с командой которую хотим запустить
cout << "Вы запустили команду и она выдала:" << endl;
cout << result << endl;
return 0;
}
теперь если запустить эту программу увидим

то есть казалось бы, ничего такого. Но хитрость в том, что список файлов, которые мы видим это прост текстовое содержимое переменной result
.
А переменную заполнила функцию exec. Вот такие вот дела.
Теперь попробуйте собрать из всей этой кучи кода задание
Задание
Напишие программу, которая будет мониторить конкретный файл и выводить в этот же файл, текст преобразованный с помощью одной из утилит
то есть вы например пишите в файл Привет
а программа преобразует содержимое файла в
________
< Привет >
--------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||