PHPのお勉強!

PHP TOP

opendir

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

opendirディレクトリハンドルをオープンする

説明

opendir(string $directory, ?resource $context = null): resource|false

ディレクトリハンドルをオープンします。このハンドルは、この後 closedir(), readdir(), rewinddir() 関数コールで使用されます。

パラメータ

directory

オープンするディレクトリのパス。

context

context パラメータの詳細については マニュアルのストリーム を参照ください。

戻り値

成功した場合にディレクトリハンドルの resource 、 失敗した場合に false を返します

エラー / 例外

失敗したときは E_WARNING が発生します。

directory が有効なディレクトリでない場合、 権限の制限によりディレクトリがオープンできない場合、 またはファイルシステムのエラー時に起こりえます。

変更履歴

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

例1 opendir() の例

<?php
$dir
= "/etc/php5/";

// 既知のディレクトリをオープンし、その内容を読み込みます。
if (is_dir($dir)) {
if (
$dh = opendir($dir)) {
while ((
$file = readdir($dh)) !== false) {
echo
"filename: $file : filetype: " . filetype($dir . $file) . "\n";
}
closedir($dh);
}
}
?>

上の例の出力は、 たとえば以下のようになります。

filename: . : filetype: dir
filename: .. : filetype: dir
filename: apache : filetype: dir
filename: cgi : filetype: dir
filename: cli : filetype: dir

参考

  • is_dir() - ファイルがディレクトリかどうかを調べる
  • readdir() - ディレクトリハンドルからエントリを読み込む
  • dir() - ディレクトリクラスのインスタンスを返す

add a note

User Contributed Notes 33 notes

up
8
sergio dot barrios at upr dot edu dot cu
8 years ago
iterated function that searches a folder or file in a directory.

<?php

$root
= '../Classes';
$search_parameter = "CachedObjectStorageFactory.php";

//if we call the function spider as spider($root);
//will show all the directory content including subdirectories

//if we call the function spider as spider('../Classes', 'Shared');
//and will show the address of the directory

spider($root, $search_parameter);
closedir();

function
spider($dir,$fileName=""){

$handle = opendir($dir);

while(
$file= readdir($handle)){

if(
$file != "." && $file != ".."){

if(
$fileName=="")
echo
$dir."/".$file."<br>";
else
if(
$file == $fileName)
echo
$dir."/".$file."<br>";


if(!
is_file($dir."/".$file))
spider($dir."/".$file,$fileName);

}
}

}

?>
up
9
hz_php at hotmail dot com { hussam alzahabi }
8 years ago
Sometimes the programmer needs to access folder content which has arabic name but the opendir function will return null resources id

for that we must convert the dirname charset from utf-8 to windows-1256 by the iconv function just if the preg_match function detect arabic characters and use " U " additionality to enable multibyte matching

<?php

$dir
= ("./"); // on this file dir

// detect if the path has arabic characters and use " u " optional to enable function to match multibyte characters

if (preg_match('#[\x{0600}-\x{06FF}]#iu', $dir) )
{

// convert input ( utf-8 ) to output ( windows-1256 )

$dir = iconv("utf-8","windows-1256",$dir);

}

if(
is_dir($dir) )
{


if( (
$dh = opendir($dir) ) !== null )
{


while ( (
$file = readdir($dh) ) !== false )
{


echo
"filename: ".$file ." filetype : ".filetype($dir.$file)."<br/>";


}

}


}

?>
up
8
DaveRandom
15 years ago
A couple of notes on Matt's posts on Windows Network Drives:

Since the system() command writes the output of the executed shell command straight to the output buffer, if you wish to hide the return of the mapping command (i.e. "The command completed succesfully" or an error message) from a web browser, you need to alter the command that is sent to the shell so that the output of that command is hidden.

You probably thinking "why not just use exec()?", and it's a reasonable question, but for some reason it doesn't always work - I guess it's another NT user permissions issue. If you want to guarantee you app will work with no messing around on the host system, use the system() command.

In the Windows command shell, you can hide the output of a command by sending both the output (1) and error (2) messages to "nul" using pipes, in other words ">nul 2>&1" on the end of the command. The username and password order in the "net use..." command needs switching in Matt's post.

Here (http://networkm.co.uk/static/drive.html) is a function I wrote to dynamically choose which drive letter to use, based on what is currently mapped and accessible to PHP.

<?php

// Define the parameters for the shell command
$location = "\\servername\sharename";
$user = "USERNAME";
$pass = "PASSWORD";
$letter = "Z";

// Map the drive
system("net use ".$letter.": \"".$location."\" ".$pass." /user:".$user." /persistent:no>nul 2>&1");

// Open the directory
$dir = opendir($letter.":/an/example/path")

...

?>
up
2
sandy at montana-riverboats dot com
20 years ago
<?php
/*
** This recursive file lister only slurps in one page at time,
** so it doesn't take forever to load when operating over
** a large system.....comes with an "Up" link for every page too.
*/

$PHP_SELF = $_SERVER['PHP_SELF'];
$DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];
# activate the next line (and deactivate the last) to
# use this script in a $DOCUMENT_ROOT/~anybody
# environment.
#$DOCUMENT_ROOT="/home/sandy/public_html/";

$tdir = $_GET['dir'];
echo
"tdir==$tdir<br>";
$tparent_path = $_GET['parent_path'];
$dbg = $_GET['dbg'];

if(!
strstr($tdir, $DOCUMENT_ROOT))
$tdir = getcwd();
if(!
strstr($tparent_path, $DOCUMENT_ROOT))
$tparent_path = $tdir;

if (!isset (
$tdir))
{
$dir = getcwd ();
}
else
$dir = $tdir;

if (!isset (
$tparent_path))
{
$parent_path = $dir;
}
else
$parent_path = $tparent_path;

echo
"<br>";
if (!isset (
$tdir))
{
$upurl = $PHP_SELF;
}
else
{
if (
$parent_path == $DOCUMENT_ROOT)
$parent_parent_path = $parent_path;
else
$parent_parent_path = dirname ($parent_path);
$upurl = $PHP_SELF."?dir=".$parent_path."&parent_path=".
$parent_parent_path;
}

if(
$dbg==1)
{
echo
"PHP_SELF: $PHP_SELF<br>\n";
echo
"DOCUMENT_ROOT: $DOCUMENT_ROOT<br>\n";
echo
"dir: $dir<br>\n";
echo
"parent_path: $parent_path<br>\n";
echo
"upurl: $upurl<br>\n";
}

echo
"<a href=\"$upurl\"> <h3>Up</h3> </a>\n";
echo
"<h2>$dir</h2>\n";

create_tree ($dir, $parent_path);

function
urlFromPath ($path)
{
global
$PHP_SELF;
global
$DOCUMENT_ROOT;
$prefix = "";
if (
substr ($path, 0, 1) != "/")
$prefix = "/";
$url = $prefix.ereg_replace ($DOCUMENT_ROOT, "", $path);
return
$url;
}

function
create_tree ($dir, $parent_path)
{
if (
$handle = opendir ($dir))
{
$i = 0;
while (
false !== ($file = @readdir ($handle)))
{
if (
$file != "." && $file != "..")
{
$list[$i] = $file;
$i++;
}
}
$dir_length = count ($list);
echo
"<ul>";
for (
$i = 0; $i < $dir_length; $i++)
{
global
$PHP_SELF;
global
$DOCUMENT_ROOT;
$label = $list[$i];
$test = $dir."/".$label;
$alink = $dir."/".ereg_replace(" ","%20",$label);
if (!
strstr ($PHP_SELF, $label))
{
if (
is_dir ($test))
{
$tmp = $PHP_SELF. "?dir=".$alink."&parent_path=".$dir;
$url = ereg_replace(" ", "%20", $tmp);
echo
"$url<br>\n";
echo
"<a href=\"$url\"><b>$label</b>/</a><br>\n";
}
else
{
$link = urlFromPath ($alink);

$label = $list[$i];
echo
"<a href=\"$link\">".$label."</a><br>\n";
}
}
}
echo
"</ul>";
closedir ($handle);
}
}

?>
up
1
Alex Dawn
1 year ago
<?php

/**
* These functions pair up nicely with generators, to hide away
* all the messy file handlers (a bit like python's with blocks)
* remove the echos they are just to demo how the generator
* works with the foreach loop.
*
* @param string $filepath
* @return Generator<string>
*/
function generateFiles(string $filepath): Generator
{
echo
"opening handle" . PHP_EOL;
$handle = opendir($filepath);
// looks more complex than needed but the docs says the type check is important
// https://www.php.net/manual/en/function.readdir.php
try {
while (
false !== ($entry = readdir($handle))) {
yield
$entry;
}
} finally {
closedir($handle);
echo
"closed handle" . PHP_EOL;
}
}

foreach (
generateFiles('.') as $file) {
echo
$file . PHP_EOL;
}
up
2
Lasse Dalegaard
19 years ago
I made a function for finding all files in a specified directory and all subdirectories. It can be quite usefull when searching in alot of files in alot subdirectories. The function returns an array with the path of all the files found.

<?
function getFiles($directory) {
// Try to open the directory
if($dir = opendir($directory)) {
// Create an array for all files found
$tmp = Array();

// Add the files
while($file = readdir($dir)) {
// Make sure the file exists
if($file != "." && $file != ".." && $file[0] != '.') {
// If it's a directiry, list all files within it
if(is_dir($directory . "/" . $file)) {
$tmp2 = getFiles($directory . "/" . $file);
if(is_array($tmp2)) {
$tmp = array_merge($tmp, $tmp2);
}
} else {
array_push($tmp, $directory . "/" . $file);
}
}
}

// Finish off the function
closedir($dir);
return $tmp;
}
}

// Example of use
print_r(getFiles('.')); // This will find all files in the current directory and all subdirectories
?>
up
1
mstabile75 at gmail dot com
18 years ago
In my previous post I ran into a problem with the "global" definition of $directorylist. If I called the function more than once on the same page it would combine the file lists. I looked at Lasse Dalegaard's example and used the following solution.

remove global definition
global $directorylist;

REPLACE
<?
if ((($maxlevel) == "all") or ($maxlevel > $level)) {
filelist($startdir . $file . "/", $searchSubdirs, $directoriesonly, $maxlevel, $level + 1);
}
?>
WITH
<?
if ((($maxlevel) == "all") or ($maxlevel > $level)) {
$list2 = filelist($startdir . $file . "/", $searchSubdirs, $directoriesonly, $maxlevel, $level + 1);
if(is_array($list2)) {
$directorylist = array_merge($directorylist, $list2);
}
}
?>
up
1
Peter Hkansson
17 years ago
Would you like to view your directories in your browser this script might come in handy.

<?php
$sub
= ($_GET['dir']);
$path = 'enter/your/directory/here/';
$path = $path . "$sub";
$dh = opendir($path);
$i=1;
while ((
$file = readdir($dh)) !== false) {
if(
$file != "." && $file != "..") {
if (
substr($file, -4, -3) =="."){
echo
"$i. $file <br />";
}else{
echo
"$i. <a href='?dir=$sub/$file'>$file</a><br />";
}
$i++;
}
}
closedir($dh);
?>
up
1
MetaNull
17 years ago
An other way to recursively walk a directory and it's content, applying a callback to each file.

Exemple: Update the last modification time of each file in a folder

<?php

clearstatcache
();

$sourcepath = "C:/WINDOWS/TEMP";

// Replace \ by / and remove the final / if any
$root = ereg_replace( "/$", "", ereg_replace( "[\\]", "/", $sourcepath ));
// Touch all the files from the $root directory
if( false === m_walk_dir( $root, "m_touch_file", true )) {
echo
"'{$root}' is not a valid directory\n";
}

// Walk a directory recursivelly, and apply a callback on each file
function m_walk_dir( $root, $callback, $recursive = true ) {
$dh = @opendir( $root );
if(
false === $dh ) {
return
false;
}
while(
$file = readdir( $dh )) {
if(
"." == $file || ".." == $file ){
continue;
}
call_user_func( $callback, "{$root}/{$file}" );
if(
false !== $recursive && is_dir( "{$root}/{$file}" )) {
m_walk_dir( "{$root}/{$file}", $callback, $recursive );
}
}
closedir( $dh );
return
true;
}

// if the path indicates a file, run touch() on it
function m_touch_file( $path ) {
echo
$path . "\n";
if( !
is_dir( $path )) {
touch( $path );
}
}

?>
up
1
chrys at mytechjournal dot com
19 years ago
I wrote a function to recursively delete files from a starting directory. I had to do this because my server doesn't allow me to delete files that apache writes because I don't have permissions, so... I let apache do the work.

<?php
$dir
= "/path/to/base/dir";

recursive_delete($dir);

function
recursive_delete( $dir )
{
if (
is_dir($dir)) {
if (
$dh = opendir($dir)) {
while ((
$file = readdir($dh)) !== false ) {
if(
$file != "." && $file != ".." )
{
if(
is_dir( $dir . $file ) )
{
echo
"Entering Directory: $dir$file<br/>";
recursive_delete( $dir . $file . "/" );
echo
"Removing Directory: $dir$file<br/><br/>";
rmdir( $dir . $file );
}
else
{
echo
"Deleting file: $dir$file<br/>";
unlink( $dir . $file );
}
}
}
closedir($dh);
}
}
}
?>
up
1
mana at averna dot com
17 years ago
I was trying to access network drives using this opendir function. I read so many posts saying that it was almost impossible to access a network drive and finally, I found the answer; there are 2 steps to be followed to access a network drive with PHP either on the same machine or another machine.

But first of all, here's the error I was getting:
Warning: opendir(\\server\folder1\sub_folder) [function.opendir]: failed to open dir: No error in C:\wamp\www\PMOT\v0.1\REPORT_MENU\index.php on line 17

Firstly, one must make sure that the folder \\server\folder1\sub_folder can be accessed by a user, let's say USER_TEST with a password PASS_TEST. By setting properties to this folder, one can add this given user with the correct password (USER_TEST with PASS_TEST).

Secondly, the APACHE service must be set-up to take this user into account. If no user is specified, APACHE uses an anonymous user and this is where the problem/error message is coming from. One must go in control panel->administrative tools->services. One will see the list of services and must look for APACHE with Apache/2.X.X in the description. (For Wampserver, it will be called wampapache, and so on!) Right click on that and pop up the properties screen. In the tab LOG ON, there are 2 options: local system account and "this account" which will be a user specified account. This is where one must specify the USER_TEST and PASS_TEST.

Following these steps worked perfectly for me but if either the folder privileges or apache log on user is disabled, then I get the initial aforementioned error message.

Anyways, I hope this can help out someone!

Cheers!

Marc
up
1
archipel dot gb at online dot fr
16 years ago
Here are two versions of the same function to list all files in a directory tree.

The first one is recursive (calls itself while going through subdirectories) :
<?php
function rec_listFiles( $from = '.')
{
if(!
is_dir($from))
return
false;

$files = array();
if(
$dh = opendir($from))
{
while(
false !== ($file = readdir($dh)))
{
// Skip '.' and '..'
if( $file == '.' || $file == '..')
continue;
$path = $from . '/' . $file;
if(
is_dir($path) )
$files += rec_listFiles($path);
else
$files[] = $path;
}
closedir($dh);
}
return
$files;
}
?>

The second one is iterative (uses less memory) :
<?php
function listFiles( $from = '.')
{
if(!
is_dir($from))
return
false;

$files = array();
$dirs = array( $from);
while(
NULL !== ($dir = array_pop( $dirs)))
{
if(
$dh = opendir($dir))
{
while(
false !== ($file = readdir($dh)))
{
if(
$file == '.' || $file == '..')
continue;
$path = $dir . '/' . $file;
if(
is_dir($path))
$dirs[] = $path;
else
$files[] = $path;
}
closedir($dh);
}
}
return
$files;
}
?>
The iterative version should be a little faster most of the time, but the big difference is in the memory usage.

Here is also a profiling function (works in php5 only) :
<?php
function profile( $func, $trydir)
{
$mem1 = memory_get_usage();
echo
'<pre>-----------------------
Test run for '
.$func.'() ...
'
; flush();

$time_start = microtime(true);
$list = $func( $trydir);
$time = microtime(true) - $time_start;

echo
'Finished : '.count($list).' files</pre>';
$mem2 = memory_get_peak_usage();

printf( '<pre>Max memory for '.$func.'() : %0.2f kbytes
Running time for '
.$func.'() : %0.f s</pre>',
(
$mem2-$mem1)/1024.0, $time);
return
$list;
}
?>
up
0
NerdyDork
17 years ago
Here is a snippet to create a site map of all html files in a folder:

<?php
// read all html file in the current directory
if ($dh = opendir('./')) {
$files = array();
while ((
$file = readdir($dh)) !== false) {
if (
substr($file, strlen($file) - 5) == '.html') {
array_push($files, $file);
}
}
closedir($dh);
}

// Sort the files and display
sort($files);
echo
"<ul>\n";
foreach (
$files as $file) {
$title = Title($file);
echo
"<li><a href=\"$file\" title=\"$title\">$title</a></li>\n";
}
echo
"</ul>\n";

// Function to get a human readable title from the filename
function Title($filename) {
$title = substr($filename, 0, strlen($filename) - 5);
$title = str_replace('-', ' ', $title);
$title = ucwords($title);
return
$title;
}
?>
up
0
tim2005
18 years ago
Hello,

A friend of mine is running a webhost, I think i found a security leak with this script:

<?php
function select_files($dir, $label = "", $select_name, $curr_val = "", $char_length = 30) {
$teller = 0;
if (
$handle = opendir($dir)) {
$mydir = ($label != "") ? "<label for=\"".$select_name."\">".$label."</label>\n" : "";
$mydir .= "<select name=\"".$select_name."\">\n";
$curr_val = (isset($_REQUEST[$select_name])) ? $_REQUEST[$select_name] : $curr_val;
$mydir .= ($curr_val == "") ? " <option value=\"\" selected>...\n" : "<option value=\"\">...\n";
while (
false !== ($file = readdir($handle))) {
$files[] = $file;
}
closedir($handle);
sort($files);
foreach (
$files as $val) {
if (
is_file($dir.$val)) { // show only real files (ver. 1.01)
$mydir .= " <option value=\"".$val."\"";
$mydir .= ($val == $curr_val) ? " selected>" : ">";
$mydir .= (strlen($val) > $char_length) ? substr($val, 0, $char_length)."...\n" : $val."\n";
$teller++;
}
}
$mydir .= "</select>";
}
if (
$teller == 0) {
$mydir = "No files!";
} else {
return
$mydir;
}
}

echo
select_files("C:/winnt/", "", "", "", "60");
?>

Now i can see hist files in his windows dir. Is this a leak? and is it fixable? I'll report this as bug too!

Tim2005
up
0
tozeiler
18 years ago
"opendir" said:
------------------------------------------------------------------

23-Jan-2006 08:04
I Just wanted a directory list and a clickable link to download the files

<snip>
------
<?
echo ("<h1>Directory Overzicht:</h1>");

function getFiles($path) {

<snip complicated function contents>

------------------------------------------------------------------
Here's a more straightforward way to linkify $path/files:

<?php

echo "<h1>Directory Overzicht:</h1>";

$dh = opendir($path);
while ((
$file = readdir($dh)) !== false) {
echo
"<a href='$path/$file'>$file</a><br />";
}
closedir($dh);

?>
up
0
Anonymous
19 years ago
This function sorts files by name as strings, but without regard to case. It also does some handy string formatting of the file size information.

<?
function getFiles($path) {
//Function takes a path, and returns a numerically indexed array of associative arrays containing file information,
//sorted by the file name (case insensitive). If two files are identical when compared without case, they will sort
//relative to each other in the order presented by readdir()
$files = array();
$fileNames = array();
$i = 0;

if (is_dir($path)) {
if ($dh = opendir($path)) {
while (($file = readdir($dh)) !== false) {
if ($file == "." || $file == "..") continue;
$fullpath = $path . "/" . $file;
$fkey = strtolower($file);
while (array_key_exists($fkey,$fileNames)) $fkey .= " ";
$a = stat($fullpath);
$files[$fkey]['size'] = $a['size'];
if ($a['size'] == 0) $files[$fkey]['sizetext'] = "-";
else if ($a['size'] > 1024) $files[$fkey]['sizetext'] = (ceil($a['size']/1024*100)/100) . " K";
else if ($a['size'] > 1024*1024) $files[$fkey]['sizetext'] = (ceil($a['size']/(1024*1024)*100)/100) . " Mb";
else $files[$fkey]['sizetext'] = $a['size'] . " bytes";
$files[$fkey]['name'] = $file;
$files[$fkey]['type'] = filetype($fullpath);
$fileNames[$i++] = $fkey;
}
closedir($dh);
} else die ("Cannot open directory: $path");
} else die ("Path is not a directory: $path");
sort($fileNames,SORT_STRING);
$sortedFiles = array();
$i = 0;
foreach($fileNames as $f) $sortedFiles[$i++] = $files[$f];

return $sortedFiles;
}

$files = getFiles("C:");
foreach ($files as $file) print "$file[name]<br>\n";
?>
up
0
iamnotanerd
19 years ago
Here is a snippet of the code that I created to search for a file..recursively open the directories and search for a match..

<?php
function search($target, $directory){

if(
is_dir($directory)){
$direc = opendir($directory);
while(
false !== ($file = readdir($direc))){

if(
$file !="." && $file != ".."){

if(
is_file($directory."/".$file)){
if(
preg_match("/$target/i", $file)){
echo
"<a href=\"$directory/$file\">$file</a><br>";
}
}else if(
is_dir($directory."/".$file)){
search($target,$directory."/".$file);

}

}
}
closedir($direc);
}

return ;
}
?>
up