PHP遍历文件目录

虽然目前大部分公司使用PHP的场景不会去读取目录,但在一些笔试题中还是会出现这样的题目,算是考基本功的一些体现吧。

知识点:

  1. scandir
  2. opendir
  3. DirectoryIterator

最方便的方法是使用语言自带的scandir函数:

1
2
$files = scandir('/usr/local/etc/nginx');
print_r($files);

但是一些虚拟主机的提供者由于安全原因会禁用掉scandir函数,可以使用opendir相关函数来处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$dir = '/usr/local/etc/nginx/';
function customScanDir($dir, $level = 0)
{
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
while (($file = readdir($dh)) !== false) {
echo str_repeat(' ', 2 * $level) . $file . "\n";
if (is_dir($dir . DIRECTORY_SEPARATOR . $file) && $file !== '.' && $file !== '..') {
customScanDir($dir . DIRECTORY_SEPARATOR . $file, $level + 1);
}
}
closedir($dh);
}
}
}
customScanDir($dir);

还有一种方法是使用SPL提供的DirectoryIterator迭代器来实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
$topPath = '/usr/local/etc/nginx';

function customReadDir($path, $level = 0)
{
if ($level > 5) {
return false;
}
if (!is_dir($path)) {
throw new Exception($path . ' is not a folder');
}

if (!is_readable($path)) {
echo 'No permission to ' . $path . "\n";
return false;
}

$dirIterator = new DirectoryIterator($path);

foreach ($dirIterator as $file) {
$fileName = $file->getFilename();
$absPath = $path . DIRECTORY_SEPARATOR . $fileName;
if ($fileName === '.' || $fileName === '..') {
continue;
}
if (is_dir($absPath)) {
echo str_repeat(' ', $level * 2) . '|- ' . "\033[34m" . $fileName . "\033[0m\n";
} else {
echo str_repeat(' ', $level * 2) . '|- ' . $fileName . "\n";
}

if (is_dir($absPath)) {
customReadDir($absPath, $level + 1);
}
}
}

customReadDir($topPath);