PHP скрипт, который отправляет по электронной почте список изменений в файлах, которые произошли в каталоге / подкаталогах

#php #ftp #cron

#php #ftp #cron

Вопрос:

У меня есть каталог с несколькими подкаталогами, в которые пользователи добавляют файлы через FTP. Я пытаюсь разработать php скрипт (который я буду запускать как задание cron), который будет проверять каталог и его подкаталоги на наличие любых изменений в файлах, размерах файлов или измененных датах. Я долго и упорно искал и пока нашел только один работающий скрипт, который я пытался модифицировать — оригинал находится здесь — однако, похоже, он отправляет только первое уведомление по электронной почте, показывая мне, что указано в каталогах. Он также создает текстовый файл с содержимым каталога и подкаталога, но когда скрипт запускается во второй раз, кажется, что он зависает, и я получаю электронное письмо без содержимого.

Кто-нибудь знает простой способ сделать это на php? Найденный мной скрипт довольно сложный, и я часами безуспешно пытался его отладить.

Заранее спасибо!

Комментарии:

1. Какого размера файлы, которые вы отслеживаете?

Ответ №1:

Поехали:

 $log = '/path/to/your/log.js';
$path = '/path/to/your/dir/with/files/';
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);
$result = array();

foreach ($files as $file)
{
    if (is_file($file = strval($file)) === true)
    {
        $result[$file] = sprintf('%u|%u', filesize($file), filemtime($file));
    }
}

if (is_file($log) !== true)
{
    file_put_contents($log, json_encode($result), LOCK_EX);
}

// are there any differences?
if (count($diff = array_diff($result, json_decode(file_get_contents($log), true))) > 0)
{
    // send email with mail(), SwiftMailer, PHPMailer, ...
    $email = 'The following files have changed:' . "n" . implode("n", array_keys($diff));

    // update the log file with the new file info
    file_put_contents($log, json_encode($result), LOCK_EX);
}
  

Я предполагаю, что вы знаете, как отправить электронное письмо. Также, пожалуйста, имейте в виду, что $log файл должен храниться за пределами того, $path который вы хотите отслеживать, по понятным причинам, конечно.

Прочитав ваш вопрос во второй раз, я заметил, что вы упомянули, что хотите проверить, изменились ли файлы, я проверяю только размер и дату изменения, если вы действительно хотите проверить, отличается ли содержимое файла, я предлагаю вам использовать хэш файла, так что это:

 $result[$file] = sprintf('%u|%u', filesize($file), filemtime($file));
  

Становится таким:

 $result[$file] = sprintf('%u|%u|%s', filesize($file), filemtime($file), md5_file($file));
// or
$result[$file] = sprintf('%u|%u|%s', filesize($file), filemtime($file), sha1_file($file));
  

Но имейте в виду, что это будет намного дороже, поскольку хэш-функции должны открывать и считывать все содержимое ваших CSV-файлов размером 1-5 МБ.

Комментарии:

1. Привет, Аликс, спасибо, я имел в виду, что если изменяются имена файлов, а не содержимое файла, то первый набор кода должен быть в порядке. Я попробую! Я только что поигрался со скриптом, который помещал имена файлов, размеры и даты, измененные в таблицу mysql, а затем запрашивал таблицу по содержимому каталога при каждом запуске скрипта — но ваш метод кажется намного чище!

2. @estebannn: Вы можете заставить это работать и с MySQL, но, честно говоря, я не вижу необходимости в этом в вашем конкретном сценарии, и да, это также будет работать с подкаталогами sub (-sub-…), поскольку я использовал RecursiveDirectoryIterator класс.

3. @estebannn: Прошу прощения, но в моем коде было две ошибки, я был пьян, и я предполагаю, что мои аналитические навыки не на том уровне, на котором они должны быть, чтобы сделать мой код без ошибок. Однако сейчас они исправлены. =)

Ответ №2:

Мне так нравится sfFinder, что я написал свою собственную адаптацию:

http://www.symfony-project.org/cookbook/1_0/en/finder

https://github.com/homer6/altumo/blob/master/source/php/Utils/Finder.php

Простой в использовании, работает хорошо.

Однако для вашего использования, в зависимости от размера файлов, я бы поместил все в репозиторий git. Тогда это легко отследить.

HTH

Комментарии:

1. Спасибо за ответ! Однако я думаю, что то, что мне нужно, может быть проще этого. Рассматриваемые файлы представляют собой CSV-файлы размером 1-5 Мб. По сути, мне просто нужно в любой момент времени проверить, изменил ли пользователь файл в каталоге с момента последней проверки, а затем попросить скрипт отправить мне электронное письмо со списком файлов, которые были изменены. Еще раз, спасибо за такой быстрый ответ, это ценится!

2. @Alix: Не добавляйте другие ответы, когда вы публикуете ответы самостоятельно. Это не стильно. sfFinder поможет, но, как вы можете видеть, я также предложил использовать git для поиска дельт файлов.

3. @Homer6: Почему ты так уверен, что я за тебя проголосовал?! Ложное обвинение тоже не стильно… Что касается вашего ответа, ни один из предложенных вами вариантов не отвечает на вопрос OP и, следовательно, не ожидайте получить от него похвалу.

4. @Alix: Я не говорил, что вы проголосовали против меня. Я сказал, что вы отклонили мой ответ, как в критике. Что вы и сделали; таким образом, это не ложное обвинение. Это то, что произошло на самом деле. 🙂 Тем не менее, вы предоставили ответ, так что слава вам на этом фронте.

5. @Homer6: О! Ну, я не пытался быть грубым, просто указывал на факт. Если OP не в состоянии понять код sfFinder, он может в конечном итоге бороться с ним в течение нескольких часов, прежде чем он поймет, что он делает. Извините, если я был немного слишком резок. =)