Отбор файлов по расширению

Недавно один друг (Стас) попросил мня написать на PHP скрипт который бы сканировал папку на наличие файлов определенного типа. Меня заинтересовало такое задание, и я хочу поделиться с вами тем, что у меня получилось с соответствующими комментариями конечно.

Итак, суть задания была такова:

Скрипт сканирует папку на наличие файлов doc/docx/xls/xlsx/ppt/pptx/pdf.
Создает ненумерованный список с id=”files”
Каждый файл обрамляет в конструкцию <li><a href=”ссылка на файл”><span></span>Название файла</a></li>
Исходя из формата файла определяется класс у ссылки
На выходе получаем такую вот конструкцию:

<ul>
<li><a class="класс файла" href="ссылка на файл 1"><span></span>Название файла 1</a></li>
<li><a class="класс файла" href="ссылка на файл 2"><span></span>Название файла 2</a></li>
<li><a class="класс файла" href="ссылка на файл 3"><span></span>Название файла 3</a></li>
<li><a class="класс файла" href="ссылка на файл 4"><span></span>Название файла 4</a></li>
<ul>

Это все нужно для красоты отображения файлов на сайте.

В папке где лежит мой скрипт я создал папку с именем «1», которую мы и будем сканировать. В ней я создал 9 файлов различного типа, в том числе все те которые нам нужно будет отбирать.

Вот собственно код скрипта который у меня получился:

<?
$dir = '1'; // папка которую будем сканировать
if(is_dir($dir))
{
if($data = opendir ($dir))
{
 while (false !== ($fs = readdir ($data)))
 {
       if($fs != '.' && $fs != '..')
 {
 $files[] = $fs;
}
}
closedir ($data);
echo "Всего файлов и каталогов: ".count($files)."</br>";
$extension=array("doc","docx","xls","xlsx","ppt","pptx","pdf");
$gf=0;
for ($i=0; $i<count($files); $i++)
{
       $parts=explode(".", $files[$i]);
       if(in_array($parts[count($parts)-1], $extension))
       {
              $good_files[$gf] = $files[$i]; $gf++;
       }
}
echo "<ul id=\"files\">";
for ($i=0; $i<count($good_files); $i++)
{
       $parts=explode(".", $good_files[$i]);
       $ext=$parts[count($parts)-1]; // расширение
       if(count($parts)>2)
       {
              $name="";
              for ($j=0; $j<(count($parts)-1); $j++)
              if($j<(count($parts)-2)) $name.=$parts[$j].".";
              else $name.=$parts[$j];
       }
       else $name=$parts[0];
       echo "<li><a class=\"".$ext."\" href=\"1/".$good_files[$i]."\"><span></span>".$name."</a></li>"; // есди надо имя с расширением выводить, вместо $name пишем тут $good_files[$i]
}
echo "<ul>";
}
else echo "Не могу открыть папку ".$dir.". Возможно нехватает прав.";
}
else echo "Нет такой папки, либо это вовсе не папка.";
?>

Ну а теперь все по прядку. В самом начале в переменную $dir запишем адрес папки которую будем сканировать. В нашем случае это просто “1”. Затем с помощью функции is_dir() определим является ли наш файл директорией. Если да, то пойдем дальше и попытаемся открыть нашу директорию (если у нас есть на то права) с помощью функции opendir(). Далее у нас идет цикл while в котором мы получаем элементы каталога по их дескриптору(адресу) с помощью функции readdir(). И тут следует обратить внимание на способ проверки значения, возвращаемого функцией readdir(). У нас осуществляется проверка значения на идентичность значению FALSE, поскольку в ином случае, любой элемент каталога, чье имя может быть выражено как FALSE, остановит цикл (например, элемент с именем «0″). Поэтому мы иcпользуем оператор “!==”, который был добавлен в PHP 4. Он возвращает TRUE в том случае если значения операндов не равно, или в случае, если оно разных типов. Функция readdir() также возвращает элементы с именами “.” и “..”. Они нам не нужны, поэтому мы их отбрасываем.

После выполнения цикла все элементы каталога будут у нас в массиве $files[]. И функцией closedir() закрываем поток, который мы открыли функцией opendir(). Далее с помощью функции count() мы посчитаем количество элементов массива $files[] и выведем его.

Итак, элементы каталога мы получили, теперь начнем отбирать их по типу. Для этого сначала создадим массив подходящих нам по расширению файлов ($extension). Массив с так называемыми «хорошими» файлами я обозвал $good_files, а переменную для их подсчета – $gf. Изначально «хороших» файлов – 0. Далее у нас цикл for по общему количеству элементов каталога.

Далее с помощью функции explode() будем разбивать строки на подстроки чтобы отделить расширение от имени файла. Т.е. разделитель у нас – точка. В имени файла может быть несколько точек, поэтому имя файла может быть разбито на несколько частей. Нас интересует последняя ($parts[count($parts)-1]). После чего с помощью функции in_array() проверяем существует ли наше расширение в массиве расширений (извините за тавтологию). Если да, то имя этого файла записываем в «хорошие» ($good_files) и увеличиваем их счетчик.

Все, нужные файлы мы отобрали, теперь можем делать с ними все что угодно.

Поле этого с помощью тех же функций (explode) получим расширение и имя файла, запишем их для удобства в соответствующие переменные и подставим в html-конструкции:

echo "<li><a class=\"".$ext."\" href=\"1/".$good_files[$i]."\"><span></span>".$name."</a></li>";

Если в имени файла присутствуют точки, то объединим их в цикле путем конкатенации строк.

Вот что получилось у меня:

А вот сгенерированное содержимое тела страницы:

Всего файлов и каталогов: 9

</br> 
<ul>
<li><a class="pdf" href="1/Docfile.withdot.pdf"><span></span>Docfile.withdot</a></li>
<li><a class="docx" href="1/Docxfile.docx"><span></span>Docxfile</a></li>
<li><a class="pdf" href="1/Pdffile.pdf"><span></span>Pdffile</a></li>
<li><a class="ppt" href="1/Pptfile.ppt"><span></span>Pptfile</a></li>
<li><a class="pptx" href="1/Pptxfile.pptx"><span></span>Pptxfile</a></li>
<li><a class="xls" href="1/Xlsfile.with2dots.xls"><span></span>Xlsfile.with2dots</a></li>
<li><a class="xlsx" href="1/Xlsxfile.xlsx"><span></span>Xlsxfile</a></li>
<ul>

При добавлении стилей CSS можно все красиво оформить =)