21

I'm using the following PHP code to list all files and folders under the current directory:

<?php
    $dirname = ".";
    $dir = opendir($dirname);

    while(false != ($file = readdir($dir)))
        {
          if(($file != ".") and ($file != "..") and ($file != "index.php"))
             {
              echo("<a href='$file'>$file</a> <br />");
        }
    }
?>

The problem is list is not ordered alphabetically (perhaps it's sorted by creation date? I'm not sure).

How can I make sure it's sorted alphabetically?

Binit Ghetiya
  • 1,919
  • 2
  • 21
  • 31
David B
  • 29,258
  • 50
  • 133
  • 186

7 Answers7

43

The manual clearly says that:

readdir
Returns the filename of the next file from the directory. The filenames are returned in the order in which they are stored by the filesystem.

What you can do is store the files in an array, sort it and then print it's contents as:

$files = array();
$dir = opendir('.'); // open the cwd..also do an err check.
while(false != ($file = readdir($dir))) {
        if(($file != ".") and ($file != "..") and ($file != "index.php")) {
                $files[] = $file; // put in array.
        }   
}

natsort($files); // sort.

// print.
foreach($files as $file) {
        echo("<a href='$file'>$file</a> <br />\n");
}
codaddict
  • 445,704
  • 82
  • 492
  • 529
  • This is the first time I use PHP. I only need it to list some stuff I uploaded to my apache. Could you please show me how to store the files in an array and sort it? – David B Oct 20 '10 at 12:01
  • 1
    +1 for natsort() might even want to think about natcasesort() – Bobby Jack Oct 20 '10 at 12:05
  • 3
    @David you could use `$files = glob("/your/path/*");` – Pekka Oct 20 '10 at 12:05
  • @Pekka: that won't return hidden files. Other than the obvious 'navigation pseudo files', the question doesn't suggest whether hidden files are needed, so it's probably safer to assume they are until told otherwise. – Bobby Jack Oct 20 '10 at 12:08
  • 1
    @David B: By the way: Filenames can contain HTML-Metacharacters. So one should escape them before outputting. Also, you want to check the files being uploaded for validity. Not that one can upload php files or so, which will be executed then.. – Jan. Oct 20 '10 at 12:09
  • @Bobby good point. However this seems to be possible to circumvent: http://www.php.net/manual/en/function.glob.php#68869 – Pekka Oct 20 '10 at 12:10
  • 2
    @Pekka: Just verified that `glob` gives **sorted** output. +1 to you. – codaddict Oct 20 '10 at 12:12
  • @cod it does? That comes as a surprise! :) I rather meant glob() to fetch the data needed for your sorting suggestion. (I would still sort it explicitly, the behaviour could vary across systems.) – Pekka Oct 20 '10 at 12:14
  • @Pekka: `glob` uses an option `GLOB_NOSORT` which tells it to return unsorted output. So looks like it's default behavior is to give sorted output. – codaddict Oct 20 '10 at 12:16
  • For some reason, this doesn't print anything. I added `$dir= ".";` at the beginning (it's missing) but still nothing. – David B Oct 20 '10 at 12:23
  • @David: you need to use a `opendir` before you do a `readdir` – codaddict Oct 20 '10 at 12:25
  • I'm a php noob, but Shouldn't you do `closedir($dir);` ? – Vitim.us Feb 28 '13 at 06:10
  • Yes but what is "the order in which they are stored by the filesystem"? Does this differ between file systems? How can you have your script check what it is, since I mean, it might be running on who knows what OS? – CommaToast Nov 17 '14 at 08:14
  • If you use this code on a folder with many files (example: 100.000 files), you can run out of memory – Marco Panichi Jan 11 '23 at 08:58
6
<?php
function getFiles(){
    $files=array();
    if($dir=opendir('.')){
        while($file=readdir($dir)){
            if($file!='.' && $file!='..' && $file!=basename(__FILE__)){
                $files[]=$file;
            }   
        }
        closedir($dir);
    }
    natsort($files); //sort
    return $files;
}
?>

<html>
<head>
</head>
<body>

<h1> List of files </h1>

<ul class="dir">
    <? foreach(getFiles() as $file)
        echo "<li name='$file'><a href='$file'>$file</a></li>";
    ?>
</ul>

</body>
</html>
Vitim.us
  • 20,746
  • 15
  • 92
  • 109
2

Using glob and sort it should work.

Aif
  • 11,015
  • 1
  • 30
  • 44
2

You could put all the directory names inside an array like:

$array[] = $file; 

After that you can sort the array with:

sort($array); 

And then print the links with that content.

I hope this help.

cored
  • 61
  • 1
  • 5
2
<?php
$dirname = ".";
$dir = opendir($dirname);

while(false != ($file = readdir($dir)))
{
if(($file != ".") and ($file != "..") and ($file != "index.php"))
{
  $list[] = $file;
}
}

sort($list);

foreach($list as $item) {
echo("<a href='$item'>$item</a> <br />");
}
?>
Andrew Sledge
  • 10,163
  • 2
  • 29
  • 30
1

I'd recommend moving away from the old opendir()/readdir(). Either use glob() or if you encounter a lot of files in a directory then use the DirectoryIterator Class(es):

http://www.php.net/manual/en/class.directoryiterator.php http://www.php.net/manual/en/function.glob.php

Regards

Jan.
  • 1,925
  • 15
  • 17
  • Jan, What's the reason to not use openddir/readdir? Neither is deprecated. – Bobby Jack Oct 20 '10 at 12:10
  • because OOP is the way to go. Also the Iterator-classes have a lot of features implemented build-into php, which you would have to code manually when you use opendir(). So I believe this would also be better for performance or security reasons. – Jan. Oct 20 '10 at 12:13
-1

You can use this beautiful script:

http://halgatewood.com/free-php-list-files-in-a-directory-script/

Armesh Singh
  • 405
  • 2
  • 5
  • 12
  • Link-only answers are vulnerable to breakage. All answers are expected to contain their advice as static text. Adding a link is supportive, but there needs to be more. – mickmackusa May 11 '20 at 05:27