Файлы и каталоги в php


 Файлы и каталоги в php

Доброго всем времени суток, здравствуйте. Сегодня хочу рассказать вам о некоторых функциях PHP для работы с каталогами и файловой системой. А так как это лучше всего делать на примерах, то не откладывая это в долгий ящик я перехожу непосредственно к ним.

Итак перед нами стоит задача:

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

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

Действительно, а вдруг в выбраном нами каталоге кроме файлов находятся другие каталоги, а внутри них еще, еще и еще.

Вот тут то нам на помощь и придет рекурсия, то есть обращение функции самой к себе. Как говорится пусть машинка сама работает, она ведь железная.

Вот как я это сделал:

Свернуть код:
<?php
function read2Dir($dir, $offs="--") {
	$dir = (substr($dir,-1)=='/') ? $dir : $dir.'/';
	if (!is_dir ($dir)) 
		return;
	$dh  = opendir($dir);	
	while ( ($file = readdir($dh) ) !== false) {
		$file = $dir.$file;
		if ( (basename($file) == "..") || (basename($file) == ".") )
			continue;
		$type = filetype($file);
		// Если это каталог вызываем нашу функцию
		if ($type == "dir"){
			echo "<br />$offs<b>[$file]</b>";
			read2Dir($file, $offs."--");
		} else {
			//if ( substr ( $file, -3 ) == 'f4v' ) {	
				$f = @filesize($dir.$file);
				echo "<br />$offs $file - размер $f байт";
			//}
		}
	}
	closedir($dh);
}

//read2Dir(getcwd(),$offs='-');
read2Dir("../", $offs='-');
?>

Давайте пошагово разберем код скрипта.
Сначала я описывю функцию read2Dir(), которая собственно и будет выполнять всю работу.

Она принимает следующие параметры:

$dir
Директория, которую мы будем сканировать
$offs
Параметр который определяет вид отсупа при выводе данных в браузер

Затем с помощью условного оператора if (он просто записан немного по другому) проверяем содержится ли слэш (/) в конце директории.

И если он там есть, то оставляем все как есть, а в противном случае добавляем его в конец.

// Добавляем / если необходимо
$dir = (substr($dir,-1)=='/') ? $dir : $dir.'/';

Сначала проверяем является ли директорией на самом деле, адрес по которму нужно произвести сканирование - функция is_dir().

И если это не так выходим из функции возвращая FALSE. Ну а если это все-таки каталог, то с помощью функции opendir() получаем дескриптор каталога для последующего использования, который в свою очередь помогает функции readdir() получить элемент каталога по этому самому дескриптору.

А получать элементы каталога мы будем в цикле whille до тех пор пока элемент каталога существуют - т.е. не тождественнен FALSE. Или говоря проще в цикле будем получать элементы пока они не закончаться.

Обратите внимание, что проверять нужно именно на тождественность.

if (!is_dir ($dir)) 
	return;
// Получаем дескриптор каталога
$dh  = opendir($dir);
// Получаем в цикле данные из каталога по его дескриптору
while ( ($file = readdir($dh) ) !== false) {

В итоге должна получится примерно такая строка - (documents/file.txt), конечно если полученный элемент является файлом, ну а в противном случае полученный элемент это каталог и соответственно нам нужно снова выполнить его сканирование.

Для этого сначала функцией basename(), которая возвращает имя файла из указанного пути, проверяем не является ли полученный элемент " . " или " .. "
Если это так то пропускаем итерацию цикла whille используя оператор continue.

$file = $dir.$file;
// Проверяем не являются ли файлы каталогами . и ..
// basename — Возвращает имя файла из указанного пути
if ( (basename($file) == "..") || (basename($file) == ".") )
    // Если это так пропускаем итерацию
    continue;

Далее определяем с помощью функции filetype() определяем тип файла.
Эта функция возвращает одно из возможных значений: fifo, char, dir, block, link, file или unknown.

Но в нашем конкретном случае нас интересует тольлько dir, и если это так то тут то и запускаем рекурсию.

То есть снова вызываем нашу функцию read2Dir(), только на этот раз передаем ей текущий элемент и пристыковываем (конкатенируем) к переменной $offset дополнительный отступ.

// Определяем тип файла
$type = filetype($file);
// Если это каталог вызываем нашу функцию
if ($type == "dir"){
read2Dir($file, $offs."--");

Ну а если полученный при чтении каталога элемент, то проверяем расширение файла. Сделать это проще всего проверив на соответствие искомому расширению три последние символа.

Получаем их используя функцию substr(), которая возвращает подстроку. Причем я указал, что меня интересуют именно последние 3 символа.

Ну а дальше совсем просто.
Если расширение соответствует назначенному нами, тогда с помощью функции filesize(), которая возвращает размер указанного файла в байтах или FALSE в случае возникновения ошибки, получаем размер файла и оператором echo выводим его в браузер.

} else {
// Проверям рассширение файла
if ( substr ( $file, -3 ) == 'f4v' ) {  
    // Определяем размер файла 
    $f = filesize($file); 
    echo $file."\n";
}

И так снова, снова и снова, при необходимости опять рекурсивно вызывая нашу функцию read2Dir() работает цикл whille, пока не будет прочитан последний файл в заданной директории.

Поработали? Тогда не забываем освободить дескриптор каталога функцией closedir (), которая закрывает поток связанный с каталогом.

// Освобождаем дескриптор каталога
    closedir($dh);

Вот такая у нас получилась функция. А вызвать ее можно, например, явно задав интересующую директорию. Я выбрал директорию на один уровень выше каталога из которого запускается скрипт.
read2Dir("../");

Или же с помощью функции getcwd(), котрая возвращает имя текущего рабочего каталога.
read2Dir(getcwd());

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

Экспериментируйте на здоровье!

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

На этом сегодня все. С удовольствием отвечу на ваши вопросы, если они у вас есть. До свидания.

Автор: Сергей Зарубин

Дата: 2012-03-03

Колличество просмотров: 5198

Нравится

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

Комментарий добавил(а): ivanscm
Дата: 2012-10-18

Отлично!

Комментарий добавил(а): mara
Дата: 2012-11-24

5



Добавить новый комментарий


Введите число с картинки:

captcha