使用PHP递归列出所有带日期的文件

4

在有人标记这个问题为重复之前,请理解我已经在本网站、Google搜索和PHP.net上进行了搜索。

我想要的非常简单。我想要一个包含日期戳(最后修改时间)的网站所有文件列表。我找到了几个声称可以做到这一点的脚本,但它们都无法正常工作。

到目前为止,我发现的最好的一个是这个:

header("Pragma: public");
  header("Cache-Control: private");
  header("Content-Type: text/csv");
  header("Content-Disposition: attachment; filename=age-of-files.csv");

  $result = array();
  $handle =  opendir(".");
     while ($datei = readdir($handle))
     {
          if (($datei != '.') && ($datei != '..'))
          {
               $file = "./".$datei;
               if (!is_dir($file))
                    $result[] = $file;
          }
     }
     closedir($handle);
  foreach($result as $r)
    if (file_exists($r))
      echo substr($r,2).",".date ("m-d-Y", filemtime($r))."\r\n"; 

这对于脚本运行的目录非常有效,但它不是递归的。我需要它继续每个子目录。我的目标是拥有一个可排序的列表,以便我可以找到在某些日期前后修改的文件。
我是PHP新手,请多包涵。我在PHP.net进行了一些研究(我不断看到人们提到SPL,我不确定它代表什么或者它是什么,但也许它是一组标准的PHP类?),看起来我需要以某种方式使用RecursiveDirectoryIterator。
我发现这个脚本在纸上看起来很棒,但在我的网站上运行它只会出现一个空白屏幕。
try
{
        /*** freds home directory ***/
        $rdi = new recursiveDirectoryIterator('/',  FilesystemIterator::SKIP_DOTS | FilesystemIterator::UNIX_PATHS);
        $it = new recursiveIteratorIterator( $rdi );
        while( $it->valid())
        {
                if( !$it->isDir() )
                {
                        echo $it->current().' '.date('Y m d H:i:s', $it->getATime() )."\n";
                }

                /*** move to the next element ***/
                $it->next();
        }
}
catch(Exception $e)
{
        /*** echo the error message ***/
        echo $e->getMessage();
}

我更喜欢使用第一个脚本,因为它可以创建csv文件(易于排序),但我不确定如何将两个脚本融合在一起。请问有人能建议我如何将RDI整合到第一个脚本中吗?


尝试不使用这些符号:FilesystemIterator::SKIP_DOTS | FilesystemIterator::UNIX_PATHS - Sayed
3个回答

2

这里有一段我发现非常有效的代码

$rdi = new RecursiveDirectoryIterator("path/"); // The directory here
$rii = new RecursiveIteratorIterator($rdi);

foreach ($rii as $filename=>$cur) {
    echo $cur.' '.date('Y m d H:i:s', $cur->getATime() )."<br/>";
}

1
尝试像这样做,这与您提供的第二个示例类似:
<?php

$path = __DIR__;

if (!is_dir($path)) {
    throw new RuntimeException(sprintf('Path %s does not exist!', $path));
}

if (!is_readable($path)) {
    throw new RuntimeException(sprintf('Path %s is not readable!', $path));
}

$iterator = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($path)
);

$files = [];

foreach ($iterator as $fileInfo) {
    if ($fileInfo->isFile()) {
        $files[] = [
            $fileInfo->getFilename(),
            dirname($fileInfo->getPathname()),
            date('c', $fileInfo->getMTime())
        ];
    }
}

print_r($files);

给定一个文件结构的例子:

enter image description here

这将产生:
Array
(
    [0] => Array
        (
            [0] => .DS_Store
            [1] => /private/tmp/rec
            [2] => 2015-08-08T08:28:33+00:00
        )

    [1] => Array
        (
            [0] => .DS_Store
            [1] => /private/tmp/rec/0
            [2] => 2015-08-08T08:28:33+00:00
        )

    [2] => Array
        (
            [0] => 0.1.txt
            [1] => /private/tmp/rec/0/0.1
            [2] => 2015-08-08T08:27:58+00:00
        )

    [3] => Array
        (
            [0] => 0.txt
            [1] => /private/tmp/rec/0
            [2] => 2015-08-08T08:27:58+00:00
        )

    [4] => Array
        (
            [0] => .DS_Store
            [1] => /private/tmp/rec/1
            [2] => 2015-08-08T08:28:33+00:00
        )

    [5] => Array
        (
            [0] => .DS_Store
            [1] => /private/tmp/rec/1/1.1
            [2] => 2015-08-08T08:28:27+00:00
        )

    [6] => Array
        (
            [0] => 1.1.txt
            [1] => /private/tmp/rec/1/1.1
            [2] => 2015-08-08T08:27:58+00:00
        )

    [7] => Array
        (
            [0] => 1.txt
            [1] => /private/tmp/rec/1
            [2] => 2015-08-08T08:27:58+00:00
        )

    [8] => Array
        (
            [0] => rec.php
            [1] => /private/tmp/rec
            [2] => 2015-08-08T08:48:30+00:00
        )

)

每个匹配都被存储为一个子数组元素,其中包含:
  1. 文件名
  2. 当前目录路径
  3. 最后修改时间
它会进行一些额外的检查以确保提供的 $path 可以被读取。
现在你有了一个 $files 数组的结果集,你应该能够重复使用你第一个例子中的一些代码来输出为 .csv 文件。
希望这可以帮到你 :)

谢谢!我会试着使用它,并看看是否可以将其融入我发布的第一个示例中,因为我认为这将是一个更优雅的解决方案。 - UserX
没问题。昨天我匆忙出门,所以没有时间完成答案并进行.csv导出。现在我又要赶着出门了 :) 但是我会尽可能更新答案,而不是在主循环中创建数组,最好直接使用fputcsv()等来构建.csv文件。 - Darragh Enright

1
如果有人感兴趣,这就是我最终得到的结果。它结合了第一个答案的简单性和有效性以及我问题中第一个示例的csv。当我在Excel中打开csv文件时,我能够轻松地按日期排序。
我需要这样做的原因是为了帮助追踪我的某个站点上的一些恶意软件。通过列出所有文件,我可以按日期排序并查找添加在可疑日期的文件。或者反过来,如果我在某天发现了已知的威胁,我可以很容易地看到那天/时间修改的其他文件。它在最终清除我网站上的持久感染方面对我有很大帮助。它一直会复活,因为我无法删除所有文件。使用这个简单的脚本,我终于找到了被安装的后门shell。哇!
非常感谢两位回答者! :)
<?php
header("Pragma: public");
header("Cache-Control: private");
header("Content-Type: text/csv");
header("Content-Disposition: attachment; filename=age-of-files.csv");

$rdi = new RecursiveDirectoryIterator("."); // The directory here
$rii = new RecursiveIteratorIterator($rdi);

foreach ($rii as $filename=>$cur) {
    echo $cur.', '.date('m-d-Y', $cur->getATime() ).', '.date('H:i:s', $cur->getATime() )."\r\n";
}
?>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接