PHPのお勉強!

PHP TOP

readdir

(PHP 4, PHP 5, PHP 7, PHP 8)

readdirディレクトリハンドルからエントリを読み込む

説明

readdir(?resource $dir_handle = null): string|false

ディレクトリから次のエントリの名前を返します。 エントリ名はファイルシステム上に格納されている順番で返されます。

パラメータ

dir_handle

opendir() が事前にオープンした ディレクトリハンドルリソース。 ディレクトリハンドルを指定しなかった場合は、 opendir() が最後にオープンしたものを使用します。

戻り値

成功した場合にエントリ名、失敗した場合に false を返します。

警告

この関数は論理値 false を返す可能性がありますが、false として評価される値を返す可能性もあります。 詳細については 論理値の セクションを参照してください。この関数の返り値を調べるには ===演算子 を 使用してください。

変更履歴

バージョン 説明
8.0.0 dir_handle は、nullable になりました。

例1 ディレクトリ内の全てのエントリのリストを得る

以下の例で、readdir() の戻り値をどのように調べているかに 注目してください。戻り値が false と一致することを、明示的に (値が等しく、かつ型も等しい - 詳細は 比較演算子 を参照ください)調べています。なぜなら、そうしないと false と評価されてしまうディレクトリエントリ (例: "0" という名前のディレクトリ)があった場合にループが とまってしまうからです。

<?php

if ($handle = opendir('/path/to/files')) {
echo
"Directory handle: $handle\n";
echo
"Entries:\n";

/* ディレクトリをループする際の正しい方法です */
while (false !== ($entry = readdir($handle))) {
echo
"$entry\n";
}

/* ディレクトリをループする際の「間違った」方法です */
while ($entry = readdir($handle)) {
echo
"$entry\n";
}

closedir($handle);
}
?>

例2 カレントディレクトリの全てのエントリを一覧する。ただし . および .. は取り除く

<?php
if ($handle = opendir('.')) {
while (
false !== ($entry = readdir($handle))) {
if (
$entry != "." && $entry != "..") {
echo
"$entry\n";
}
}
closedir($handle);
}
?>

参考

  • is_dir() - ファイルがディレクトリかどうかを調べる
  • glob() - パターンにマッチするパス名を探す
  • opendir() - ディレクトリハンドルをオープンする
  • scandir() - 指定されたパスのファイルとディレクトリのリストを取得する

add a note

User Contributed Notes 29 notes

up
37
sreekumar [at] sreek [dot] in
13 years ago
A function I created to non-recursively get the path of all files and folders including sub-directories of a given folder.
Though I have not tested it completely, it seems to be working.

<?php

/**
* Finds path, relative to the given root folder, of all files and directories in the given directory and its sub-directories non recursively.
* Will return an array of the form
* array(
* 'files' => [],
* 'dirs' => [],
* )
* @author sreekumar
* @param string $root
* @result array
*/
function read_all_files($root = '.'){
$files = array('files'=>array(), 'dirs'=>array());
$directories = array();
$last_letter = $root[strlen($root)-1];
$root = ($last_letter == '\\' || $last_letter == '/') ? $root : $root.DIRECTORY_SEPARATOR;

$directories[] = $root;

while (
sizeof($directories)) {
$dir = array_pop($directories);
if (
$handle = opendir($dir)) {
while (
false !== ($file = readdir($handle))) {
if (
$file == '.' || $file == '..') {
continue;
}
$file = $dir.$file;
if (
is_dir($file)) {
$directory_path = $file.DIRECTORY_SEPARATOR;
array_push($directories, $directory_path);
$files['dirs'][] = $directory_path;
} elseif (
is_file($file)) {
$files['files'][] = $file;
}
}
closedir($handle);
}
}

return
$files;
}
?>
up
1
Mark Simon
5 years ago
PHP includes and alternative boolean operators whose precedence is below assignment. This means that an expression of the form

<?php
if(($a = something()) && $a !== false) ;
?>

can be written as

<?php
if($a = something() and $a !== false) ;
?>

In this case, the loop can be written as:

<?php
while ($entry = readdir($handle) and $entry !== false) {
// etc
}
?>
up
4
(Qube#php@Efnet)
17 years ago
Here is an updated version of preg_find() [which has been linked from the glob() man page for years] - this function should provide most of what you want back from reading files, directories, different sorting methods, recursion, and perhaps most powerful of all the ability to pattern match with a PCRE regex.

You can get preg_find here: http://www.pgregg.com/projects/php/preg_find/preg_find.php.txt
or if you prefer colourful .phps format: http://www.pgregg.com/projects/php/preg_find/preg_find.phps
or scoll down to the end of this note.

I wrote several examples on how to use it on my blog at: http://www.pgregg.com/forums/viewtopic.php?tid=73

simple glob() type replacement:
$files = preg_find('/./', $dir);

recursive?
$files = preg_find('/./', $dir, PREG_FIND_RECURSIVE);

pattern match? find all .php files:
$files = preg_find('/\.php$/D', $dir, PREG_FIND_RECURSIVE);

sorted alphabetically?
$files = preg_find('/\.php$/D', $dir, PREG_FIND_RECURSIVE|PREG_FIND_SORTKEYS);

sorted in by filesize, in descending order?
$files = preg_find('/./', $dir,
PREG_FIND_RECURSIVE|PREG_FIND_RETURNASSOC |PREG_FIND_SORTFILESIZE|PREG_FIND_SORTDESC);
$files=array_keys($files);

sorted by date modified?
$files = preg_find('/./', $dir,
PREG_FIND_RECURSIVE|PREG_FIND_RETURNASSOC |PREG_FIND_SORTMODIFIED);
$files=array_keys($files);

Ok, the PHP note says my note is too long, so please click on one of the above links to get it.
up
8
frasq at frasq dot org
14 years ago
A variation on listing all the files in a directory recursively. The code illustrates a basic technique : the use of an auxiliary function. It avoids building temporary lists which are merged on the way back. Note that the array which collects the information must be passed by reference.

<?php
function listdir($dir='.') {
if (!
is_dir($dir)) {
return
false;
}

$files = array();
listdiraux($dir, $files);

return
$files;
}

function
listdiraux($dir, &$files) {
$handle = opendir($dir);
while ((
$file = readdir($handle)) !== false) {
if (
$file == '.' || $file == '..') {
continue;
}
$filepath = $dir == '.' ? $file : $dir . '/' . $file;
if (
is_link($filepath))
continue;
if (
is_file($filepath))
$files[] = $filepath;
else if (
is_dir($filepath))
listdiraux($filepath, $files);
}
closedir($handle);
}

$files = listdir('.');
sort($files, SORT_LOCALE_STRING);

foreach (
$files as $f) {
echo
$f, "\n";
}
?>
up
7
stuart at horuskol dot net
13 years ago
Looking through the examples, I can't see any that do a simple check on the value of the directory resource that opendir returns and is subsequently used by readdir.

If opendir returns false, and you simply pass this to the readdir call in the while loop, you will get an infinite loop.

A simple test helps prevent this:

<?php

$dir
= opendir($path);
while (
$dir && ($file = readdir($dir)) !== false) {
// do stuff
}

?>
up
1
Mauro Alessandro Nonnis
13 years ago
## List and Rename all files on recursive directories with "recursive directory name" as template + filename
## Advice: other files in the same directory will result in a warning
## scriptname : Recursive Dir_Renfiles_dirname-filename.php

<?php
if ($handle = opendir('.')) {
while (
false !== ($file = readdir($handle))) {
if (
$file != "." && $file != ".." && $file != "Recursive Dir_Renfiles_dirname-filename.php") {
echo
"$file";
echo
"<br>";
$count = -1;
$handle2 = @opendir($file);
while (
false !== ($file2 = @readdir($handle2))) {
echo
"$file2";
if (
$count <10 ){ @rename("$file/$file2", "$file/$file"."_$file2");}
else { @
rename("$file/$file2", "$file/$file"."_$file2");}
echo
"<br>";
$count = $count + 1;
}
echo
"<br>";
}
}
closedir($handle);
}
?>
up
1
avi dot megladon at gmail dot com
12 years ago
loop through folders and sub folders with option to remove specific files.

<?php
function listFolderFiles($dir,$exclude){
$ffs = scandir($dir);
echo
'<ul class="ulli">';
foreach(
$ffs as $ff){
if(
is_array($exclude) and !in_array($ff,$exclude)){
if(
$ff != '.' && $ff != '..'){
if(!
is_dir($dir.'/'.$ff)){
echo
'<li><a href="edit_page.php?path='.ltrim($dir.'/'.$ff,'./').'">'.$ff.'</a>';
} else {
echo
'<li>'.$ff;
}
if(
is_dir($dir.'/'.$ff)) listFolderFiles($dir.'/'.$ff,$exclude);
echo
'</li>';
}
}
}
echo
'</ul>';
}

listFolderFiles('.',array('index.php','edit_page.php'));
?>
up
0
stiles daht nathan ahat geemale
10 years ago
I'm on 5.4.21 this function returns null after . and .. on an empty directory. ZendServer for IBMi
up
-1
synnus at gmail dot com
5 years ago
<?php

// if( $entry[0] != '.' ) best for ' . ' and ' .. '

$d = dir( '.' );
echo
"Pointeur : " . $d->handle . "\n";
echo
"Chemin : " . $d->path . "\n";
while (
false !== ($entry = $d->read())) {
if(
$entry[0] != '.') {
echo
$entry, PHP_EOL;
}
}
$d->close();

?>
up
-1
Mark Simon
5 years ago
Regarding the warning:

This function may return Boolean FALSE, but may also return a non-Boolean value which evaluates to FALSE.

Of course, this means that if you use:

<?php
if($entry = readdir($handle) == false)
?>

or

<?php
while($entry = readdir($handle))
?>

you may get a false false, as it were.

As far as I can tell, the only time this would actually occur is if you encounter an entry of 0.

According to

https://www.php.net/manual/en/language.types.boolean.php#language.types.boolean.casting

this appears to be the only string which will evaluate to false.
up
0
jpittman2 at gmail dot com
11 years ago
Warning when using readdir() on certain versions of CentOS on NFS-mounted directories:

This is not a bug with PHP's readdir, but a bug with certain versions of CentOS's readdir implementation. According to Post #6213 in the CentOS Bugs forum, when using CentOS kernel versions 2.6.18-348 through 2.6.18-348.3.1, invoking readdir on an NFS-mounted directory may not return all the entries. Since PHP's readdir() uses this library, the issue is manifest in PHP as well.

According to the post, upgrading to version 2.6.18-348.4.1.el5 should solve the issue, though I haven't tried it.

glob() does NOT seem to suffer from this same vulnerability.
up
0
Kim Christensen
16 years ago
Handy little function that returns the number of files (not directories) that exists under a directory.
Choose if you want the function to recurse through sub-directories with the second parameter -
the default mode (false) is just to count the files directly under the supplied path.

<?php

/**
* Return the number of files that resides under a directory.
*
* @return integer
* @param string (required) The directory you want to start in
* @param boolean (optional) Recursive counting. Default to FALSE.
* @param integer (optional) Initial value of file count
*/

function num_files($dir, $recursive=false, $counter=0) {
static
$counter;
if(
is_dir($dir)) {
if(
$dh = opendir($dir)) {
while((
$file = readdir($dh)) !== false) {
if(
$file != "." && $file != "..") {
$counter = (is_dir($dir."/".$file)) ? num_files($dir."/".$file, $recursive, $counter) : $counter+1;
}
}
closedir($dh);
}
}
return
$counter;
}

// Usage:
$nfiles = num_files("/home/kchr", true); // count all files that resides under /home/kchr, including subdirs
$nfiles = num_files("/tmp"); // count the files directly under /tmp

?>
up
0
info at agentur-obermaier dot de
16 years ago
This is a nice quick full dir read - sorry for my bad english ;)

<?php
function ReadDirs($dir,$em){
if (
$handle = opendir($dir)) {
while (
false !== ($file = readdir($handle))) {
if (
$file != "." && $file != ".." && $file != "Thumb.db") {
if(
is_dir($dir.$file)){
echo
$em."&raquo; ".$file.'<br>';
ReadDirs($dir.$file."/",$em."&nbsp;&nbsp;");
}
}
}
closedir($handle);
}
}
?>
up
0
schursin at gmail[deleteme] dot com
17 years ago
code:

<?php

function permission($filename)
{
$perms = fileperms($filename);

if ((
$perms & 0xC000) == 0xC000) { $info = 's'; }
elseif ((
$perms & 0xA000) == 0xA000) { $info = 'l'; }
elseif ((
$perms & 0x8000) == 0x8000) { $info = '-'; }
elseif ((
$perms & 0x6000) == 0x6000) { $info = 'b'; }
elseif ((
$perms & 0x4000) == 0x4000) { $info = 'd'; }
elseif ((
$perms & 0x2000) == 0x2000) { $info = 'c'; }
elseif ((
$perms & 0x1000) == 0x1000) { $info = 'p'; }
else {
$info = 'u'; }

// владелец
$info .= (($perms & 0x0100) ? 'r' : '-');
$info .= (($perms & 0x0080) ? 'w' : '-');
$info .= (($perms & 0x0040) ? (($perms & 0x0800) ? 's' : 'x' ) : (($perms & 0x0800) ? 'S' : '-'));

// группа
$info .= (($perms & 0x0020) ? 'r' : '-');
$info .= (($perms & 0x0010) ? 'w' : '-');
$info .= (($perms & 0x0008) ? (($perms & 0x0400) ? 's' : 'x' ) : (($perms & 0x0400) ? 'S' : '-'));

// все
$info .= (($perms & 0x0004) ? 'r' : '-');
$info .= (($perms & 0x0002) ? 'w' : '-');
$info .= (($perms & 0x0001) ? (($perms & 0x0200) ? 't' : 'x' ) : (($perms & 0x0200) ? 'T' : '-'));

return
$info;
}

function
dir_list($dir)
{
if (
$dir[strlen($dir)-1] != '/') $dir .= '/';

if (!
is_dir($dir)) return array();

$dir_handle = opendir($dir);
$dir_objects = array();
while (
$object = readdir($dir_handle))
if (!
in_array($object, array('.','..')))
{
$filename = $dir . $object;
$file_object = array(
'name' => $object,
'size' => filesize($filename),
'perm' => permission($filename),
'type' => filetype($filename),
'time' => date("d F Y H:i:s", filemtime($filename))
);
$dir_objects[] = $file_object;
}

return
$dir_objects;
}

?>

call:

<?php

print_r
(dir_list('/path/to/you/dir/'));

?>

output sample:

Array
(
[0] => Array
(
[name] => api
[size] => 0
[perm] => drwxrwxrwx
[type] => dir
[time] => 28 May 2007 01:55:02
)

[1] => Array
(
[name] => classes
[size] => 0
[perm] => drwxrwxrwx
[type] => dir
[time] => 26 May 2007 00:56:44
)

[2] => Array
(
[name] => config.inc.php
[size] => 143
[perm] => -rw-rw-rw-
[type] => file
[time] => 26 May 2007 13:13:19
)

[3] => Array
(
[name] => index.php
[size] => 131
[perm] => -rw-rw-rw-
[type] => file
[time] => 26 May 2007 22:15:18
)

[4] => Array
(
[name] => modules
[size] => 0
[perm] => drwxrwxrwx
[type] => dir
[time] => 28 May 2007 00:47:40
)

[5] => Array
(
[name] => temp
[size] => 0
[perm] => drwxrwxrwx
[type] => dir
[time] => 28 May 2007 04:49:33
)

)
up
0
(Qube#php@Efnet)
17 years ago
<?php

// Sample function to recursively return all files within a directory.
// http://www.pgregg.com/projects/php/code/recursive_readdir.phps

Function listdir($start_dir='.') {

$files = array();
if (
is_dir($start_dir)) {
$fh = opendir($start_dir);
while ((
$file = readdir($fh)) !== false) {
# loop through the files, skipping . and .., and recursing if necessary
if (strcmp($file, '.')==0 || strcmp($file, '..')==0) continue;
$filepath = $start_dir . '/' . $file;
if (
is_dir($filepath) )
$files = array_merge($files, listdir($filepath));
else
array_push($files, $filepath);
}
closedir($fh);
} else {
# false if the function was called with an invalid non-directory argument
$files = false;
}

return
$files;

}

$files = listdir('.');
print_r($files);
?>
up
0
phpwizard-at-pech-dot-cz
22 years ago
It should work, but it'll be better to read section 13.1.3 Cache-control Mechanisms of RFC 2616 available at http://rfc.net/rfc2616.html before you start with confusing proxies on the way from you and the client.

Reading it is the best way to learn how proxies work, what should you do to modify cache-related headers of your documents and what you should never do again. :-)

And of course not reading RFCs is the best way to never learn how internet works and the best way to behave like Microsoft corp.

Have a nice day!
Jirka Pech
up
-1
mrlemonade
13 years ago
Get all files on recursive directories in single array.

<?php
/*
* mrlemonade ~
*/

function getFilesFromDir($dir) {

$files = array();
if (
$handle = opendir($dir)) {
while (
false !== ($file = readdir($handle))) {
if (
$file != "." && $file != "..") {
if(
is_dir($dir.'/'.$file)) {
$dir2 = $dir.'/'.$file;
$files[] = getFilesFromDir($dir2);
}
else {
$files[] = $dir.'/'.$file;
}
}
}
closedir($handle);
}

return
array_flat($files);
}

function
array_flat($array) {

foreach(
$array as $a) {
if(
is_array($a)) {
$tmp = array_merge($tmp, array_flat($a));
}
else {
$tmp[] = $a;
}
}

return
$tmp;
}

// Usage
$dir = '/data';
$foo = getFilesFromDir($dir);

print_r($foo);
?>