Subfolder in script

Do you have a question? Post it now! No Registration Necessary.  Now with pictures!

Threaded View
Hi there.

I have found this online:
// this is used by usort()
function cmp($a, $b) {
    if ($a['mtime'] == $b['mtime']) {
        return 0;
    return ($a['mtime'] < $b['mtime']) ? -1 : 1;
// read dir and save name,size,date in array
$file_list = array();
$search_dir = '.';
$dp = opendir($search_dir);
$file_list = array();
while ($item = readdir($dp)) {
    if ((is_file($item)) AND (substr($item, 0, 1) != '.')) {
        $file_list[] = array('name' => $item, 'size' => filesize($item), 'mtime' => filemtime($item));
// Sort $file_list
usort($file_list, "cmp");
// Create a table header.
print '<hr /><br />
<table cellpadding="2" cellspacing="2" align="left">
<td><b>File Name</b></td>
<td><b>File Size</b></td>
<td><b>Last Modified</b></td>
foreach($file_list as $one_file) {
    // Print the information.
    print "<tr>
    <td><a href=\"" . $one_file['name'] . "\">" . $one_file['name'] . "</a></td>
    <td>" . $one_file['size'] . " bytes</td>
    <td>" . date('F j, Y', $one_file['mtime']) . "</td>
print '</table>'; // Close the HTML table.
closedir($dp); // Close the directory.

The .php file is stored on domain.tld/sub1

The files are at domain.tld/sub1/sub2

I want to change "$search_dir = '.';" to "$search_dir = '/sub2';"

But I cannot get it to work.
I have tried all the combinationa of sub1 / sub2, with and without "." ending and starting "/".
But no luck.


Or a better solution?

I need to create a clickable list of files.
The files are pdf files, and the links can be generated from filenames.


Re: Subfolder in script

On Tuesday 12 August 2014 08:38, in comp.lang.php, "Danjel Jungersen"

Quoted text here. Click to load it

What do you mean by "cannot get it to work"? What can you not get to work?

Quoted text here. Click to load it

It is likely that you are getting caught in a disparity between what
readdir() returns and what isfile() accepts.

readdir() only returns names. These names are not qualified pathnames, they
are simply names. They do not have any information as to the directory they
came from.

isfile() accepts pathnames. Pathnames that start with a '/' are checked
directly (i.e. "/here/there" refers to file "/here/there"), while pathnames
that do not start with a '/' are checked as relative pathnames
(i.e. "here/there" is treated as "./here/there").

Since the names returned by readdir() do not have slashes in them (they are
not allowed, as filenames to have slashes), isfile() sees them as path
names relative to the current working directory. So, while readdir() pulled
names from directory "./sub1", isfile() checks those names against
directory "." (the current working directory).

To fix, before passing the string from readdir() to isfile(), prepend it
with the search directory name you passed to opendir().

Something like...
  while ($item = readdir($dp)) {
    if ((is_file($search_dir.$item)) AND ...

Lew Pitcher
"In Skills, We Trust"
PGP public key available upon request

Re: Subfolder in script

On Tue, 12 Aug 2014 05:38:27 -0700, Danjel Jungersen wrote:

Quoted text here. Click to load it

opendir works on the filesystem, not on the url, you may need to specify  
the absolute path relative to the filesystem root, or relative to the  
current working directory, which might not be the directory the php file  
is in.

See what value is returned by a call to getcwd() immediately before  
calling opendir.

Also, when using opendir, it's always a good idea to check that the  
result is non false before using it, and handle failures gracefully.

See also

Perhaps it would also be a good idea to wrap your opendir call in an  
is_dir check and handle the case where is_dir is false as well.

"handle" means present a meaningful message to whoever is viewing the  
script output, whether it is a web page or on a console, rather than just  
ignoring the fault condition. Handling may also include some sort of  
logging. See also the handy error_log() function.

eg (adapted from the manual example for opendir, not actually tested):

if ( is_dir( $dir ) ) {
    if ( $dh = opendir( $dir ) ) {
            /* search through files */
        closedir( $dh );
    else {
        /* opendir failed */
        error_log( "opendir failed, cwd was '".getcwd()."' and $dir was  
''",1,"" );
        echo "<p>A server error occurred. The system maintainer has been  
notified and will investigate this. Please try again later.</p>";
else {
    /* is_dir returned false */
    error_log( "is_dir returned false for '', cwd was '".getcwd
()"'",1,"" );
    echo "<p>A server error occurred. The system maintainer has been  
notified and will investigate this. Please try again later.</p>";

Denis McMahon,

Re: Subfolder in script

Quoted text here. Click to load it

You mean that you want to list the files in sub2.  You don't want to
change $search_dir to "/sub2" because that's the name of another
directory altogether!

Quoted text here. Click to load it

In a perfect world, programming would not be about luck, but it is.  You
had the bad luck come across some code that could not be easily altered.

Step one is to set $search_dir = "sub2";.  But this will cause the array
to be populated with the names of the files in sub2, but they are not
know by that name to code whose current working directory in sub1.  For
example, sub2 may have a file "doc.pdf", but evaluating
filesize("doc.pdf") will get you nowhere.  The file's name (from here)
is "sub2/doc.pdf".

Quick fix:

  while ($fname = readdir($dp)) {
       $item = "$search_dir/$fname";
       /* code as before */

Quoted text here. Click to load it

Blimey!  Too many to name, but I'd consider using the glob function
first of all.  glob("$search_dir/*") will give you the names properly
prefixed so it is simpler to change where files are to be found.  Also
you will be able to say things like glob("$search_dir/*.pdf") which may
well be useful later.

Another thing would be to use the stat function and to store the result
array directly, rather than picking out just those fields that you need
(which is probably what filesize and filemtime are doing behind your
back).  Unless there are a very large number of files, it just won't be
worth doing anything else:

  $file_list = array_map(function ($fn) {
                           $s = stat($fn); $s['name'] = $fn; return $s;
                         }, glob("$search_dir/*"));
  usort($file_list, "cmp");

You may want to string the directory name off the front when writing the
list, and you may need to change the anonymous function to being a named
one if you can't rely on a recent version of PHP.


Site Timeline