Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.php > #14166 > unrolled thread

Subfolder in script

Started byDanjel Jungersen <danjel@jungersen.dk>
First post2014-08-12 05:38 -0700
Last post2014-08-12 16:27 +0100
Articles 4 — 4 participants

Back to article view | Back to comp.lang.php


Contents

  Subfolder in script Danjel Jungersen <danjel@jungersen.dk> - 2014-08-12 05:38 -0700
    Re: Subfolder in script Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2014-08-12 10:08 -0400
    Re: Subfolder in script Denis McMahon <denismfmcmahon@gmail.com> - 2014-08-12 14:27 +0000
    Re: Subfolder in script Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-08-12 16:27 +0100

#14166 — Subfolder in script

FromDanjel Jungersen <danjel@jungersen.dk>
Date2014-08-12 05:38 -0700
SubjectSubfolder in script
Message-ID<4a738670-21a1-4de4-9ed9-d9db7d19138c@googlegroups.com>
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">
<tr>
<td><b>File Name</b></td>
<td><b>File Size</b></td>
<td><b>Last Modified</b></td>
</tr>';
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>
    </tr>\n";
}
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.

Anyone?

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.

:-)
Danjel 

[toc] | [next] | [standalone]


#14167

FromLew Pitcher <lew.pitcher@digitalfreehold.ca>
Date2014-08-12 10:08 -0400
Message-ID<IdpGv.264925$HF6.82822@fx30.iad>
In reply to#14166
On Tuesday 12 August 2014 08:38, in comp.lang.php, "Danjel Jungersen"
<danjel@jungersen.dk> wrote:

> 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">
> <tr>
> <td><b>File Name</b></td>
> <td><b>File Size</b></td>
> <td><b>Last Modified</b></td>
> </tr>';
> 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>
>     </tr>\n";
> }
> 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.

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


> I have tried all the combinationa of sub1 / sub2, with and without "."
> ending and starting "/". But no luck.

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

[toc] | [prev] | [next] | [standalone]


#14168

FromDenis McMahon <denismfmcmahon@gmail.com>
Date2014-08-12 14:27 +0000
Message-ID<lsd88n$q99$2@dont-email.me>
In reply to#14166
On Tue, 12 Aug 2014 05:38:27 -0700, Danjel Jungersen wrote:

> $search_dir = '.';

> 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';"

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 http://php.net/manual/en/function.opendir.php

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.

http://uk1.php.net/manual/en/function.error-log.php

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 
'{$dir}'",1,"name@example.com" );
        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 '{$dir}', cwd was '".getcwd
()"'",1,"name@example.com" );
    echo "<p>A server error occurred. The system maintainer has been 
notified and will investigate this. Please try again later.</p>";
}

-- 
Denis McMahon, denismfmcmahon@gmail.com

[toc] | [prev] | [next] | [standalone]


#14169

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2014-08-12 16:27 +0100
Message-ID<87ppg5sp7p.fsf@bsb.me.uk>
In reply to#14166
Danjel Jungersen <danjel@jungersen.dk> writes:

> 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">
> <tr>
> <td><b>File Name</b></td>
> <td><b>File Size</b></td>
> <td><b>Last Modified</b></td>
> </tr>';
> 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>
>     </tr>\n";
> }
> 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';"

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!

> 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.

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 */
  }

> Or a better solution?

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.

<snip>
-- 
Ben.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.php


csiph-web