Welcome to WebmasterWorld Guest from 23.20.137.66

Forum Moderators: coopster & jatar k

Message Too Old, No Replies

Counting Files In A Directory

I think I'm close but still having trouble...

     
6:19 am on Jul 21, 2010 (gmt 0)

5+ Year Member



I'm trying to list and count files in a directory and then echo back the results. The problem I'm having if the result seems to loop. The code I'm using is below. Can anyone help?

$dir = 'myfolder';
$files = scandir($dir);
foreach ($files as &$file) {
if ($file!='.' && $file!='..' )
{
while (list($key,$value) = each($files)) {
echo $key . $dir . $value
}
}
}
7:32 am on Jul 21, 2010 (gmt 0)

WebmasterWorld Senior Member 5+ Year Member



Hi there Capulet_x,

Something like this would be sufficient

$dir = 'myfolder';
$counter = array();
$i = "0";
$files = scandir($dir);
foreach ($files as &$file) {
if (($file != '.') && ($file!='..'))
{
$counter[] = $file[$i];
$i++;
}
}

echo count($counter);

Typed on the fly, but you get the idea. ( I think it's right anyway ;) )

Cheers,
MRb
5:40 pm on Jul 21, 2010 (gmt 0)

WebmasterWorld Senior Member rocknbil is a WebmasterWorld Top Contributor of All Time 10+ Year Member



What is happening is you are already looping through the files, then on each iteration you do a while on each file for the entire files array, an exponential loop (though not recursive, it will end eventually.) Good thing it didn't crash. :-)

You only need one loop. You don't need the file reference &, this is used when, if you change a variable's value, it will change outside of the scope of a function as well, or you want to "make a copy" of a variable and modify the copy without affecting the original variable value. Don't have to understand that at this point, just know you shouldn't need it for a loop iterator, it is a temporary variable. :-)


// Executable from **anywhere**
$dir = 'myfolder';
$files = scandir("$_SERVER[DOCUMENT_ROOT]/$dir");
echo "<ul>";
foreach ($files as $file) {
if ($file!='.' && $file!='..' ) {
// Or . . match on the extensions you want, more common
echo "<li>$dir/$file</li>";
}
}
echo "</ul>";
7:00 pm on Jul 21, 2010 (gmt 0)

WebmasterWorld Senior Member 5+ Year Member



Hi all,

Sorry about my original post, I'm not sure what I had had to drink before work this morning, but I just dug out a piece of code that will suit your needs, literally just counts the files in a specified directory and returns the numerical value - quite useful, though with a few tweeks from rocknbils suggestion this will do nicely :)

function ScanDirectory($DirList){
$DirRead = array();
$DirReadList = opendir($DirList);

//read specified directory & an store instances in array
while($DirGot = readdir($DirReadList)){
if(($DirGot != ".") && ($DirGot != "..")){
$DirRead[] = $DirGot;
}
}

return count($DirRead);
}



Hope that's a better suggestion for you - just pass the directory you want to scan into the function and it will echo the number of file like this:-

echo ScanDirectory("a_directory_to_scan/");


[EDIT]: Sorry I couldn't help myself, this is an amalgamation of mine and Rocknbils suggestions

function ScanCountList($dir){

$files = scandir($dir);

$counter = array();
$first = "<ul>";

foreach ($files as $file) {
if ($file!='.' && $file!='..' ) {
$counter[] = $file;
// Or . . match on the extensions you want, more common
$first .= "<li>$dir/$file</li>";
}
}
$first .= "</ul>";
return array($first,count($counter));
}

$Listings = ScanCountList('Your/path/to/directory/');

echo "File listing:-";
echo "<br>";
echo $Listings['0'];
echo "<br>";
echo "There are ".$Listings['1']." File".(($Listings['1'] > 1) ? '(s)':'')." in the Directory you specified";


That should do just nicely - and thanks to Rocknbil for giving me the idea too ;)

Cheers,
MRb
1:27 am on Jul 22, 2010 (gmt 0)

5+ Year Member



Thanks so much for all of your effort and input. I tried some of the solutions here but I'm still not getting the output that I was looking for.
In my directory if I have 5 image files; for example:

dog.jpg
mouse.jpg
cat.jpg
tree.jpg
car.jpg

I would like the script to output:

1 dog.jpg
2 mouse.jpg
3 cat.jpg
4 tree.jpg
5 car.jpg

I would like the script to list the files and then prefix them with a corresponding number as above. Thats what I was trying to do with my original script but as rockinbil suggested my script created an exponential loop. I'm still trying to straighten it out.
2:40 am on Jul 22, 2010 (gmt 0)

WebmasterWorld Senior Member rocknbil is a WebmasterWorld Top Contributor of All Time 10+ Year Member



Same thing, just use OL?


$dir = 'myfolder';
$files = scandir("$_SERVER[DOCUMENT_ROOT]/$dir");
echo "<ol>";
foreach ($files as $file) {
if (preg_match('/\.jpe*g$/i',$file)) {
echo "<li>$dir/$file</li>";
}
}
echo "</ol>";


OR if you want a physical number, indices start at 0, so



$dir = 'myfolder';
$files = scandir("$_SERVER[DOCUMENT_ROOT]/$dir");
echo "<ul>";
$count = count($files);
for ($i=0;$i<$count;$i++) {
$num=$i+1;
if (preg_match('/\.jpe*g$/i',$file)) {
echo "<li>$num $dir/$file</li>";
}
}
echo "</ul>";


Note (I think) scandir is PHP5+ only, M's use of readdir is backwards compatible for older version.
6:26 am on Jul 22, 2010 (gmt 0)

5+ Year Member



Thank you, rockinbil...
Although I still was not getting the output as I indicated above. I changed a few things that got me closer but now I'm getting another looping issue.

$dir = 'myfolder/';
$files = scandir("$dir");
$count = count($files);
for ($i=0;$i<$count;$i++) {
$num=$i+1;
foreach ($files as $file) {
if (preg_match('/\.jpe*g$/i',$file)) {
echo "<li>$num $dir/$file</li>";
}
}
}

This is the output I get:

1 myfolder/dog.jpg
1 myfolder/mouse.jpg
1 myfolder/cat.jpg
2 myfolder/dog.jpg
2 myfolder/mouse.jpg
2 myfolder/cat.jpg
3 myfolder/dog.jpg
3 myfolder/mouse.jpg
3 myfolder/cat.jpg
4 myfolder/dog.jpg
4 myfolder/mouse.jpg
4 myfolder/cat.jpg
5 myfolder/dog.jpg
5 myfolder/mouse.jpg
5 myfolder/cat.jpg
6 myfolder/dog.jpg
6 myfolder/mouse.jpg
6 myfolder/cat.jpg
7 myfolder/dog.jpg
7 myfolder/mouse.jpg
7 myfolder/cat.jpg
8 myfolder/dog.jpg
8 myfolder/mouse.jpg
8 myfolder/cat.jpg
9 myfolder/dog.jpg
9 myfolder/mouse.jpg
9 myfolder/cat.jpg

I think that the reason that it counted out to 9 was that there was a .gif file and a few .png files in the same folder as the jpegs. I would like it to output

1 myfolder/dog.jpg
2 myfolder/mouse.jpg
3 myfolder/cat.jpg

For some reason "$_SERVER[DOCUMENT_ROOT]" generated an error.
7:30 am on Jul 22, 2010 (gmt 0)

WebmasterWorld Senior Member 5+ Year Member



Hi there capulet_x,

function ScanCountList($dir){

$files = scandir($dir);

$counter = array();
$first = "<ol>";

foreach ($files as $file) {
if ($file!='.' && $file!='..' ) {
$counter[] = $file;
// Or . . match on the extensions you want, more common
$first .= "<li>$file</li>";
}
}
$first .= "</ol>";
return array($first,count($counter));
}

$Listings = ScanCountList('Your/path/to/directory/');

echo "File listing:-";
echo "<br>";
echo $Listings['0'];
echo "<br>";
echo "There are ".$Listings['1']." File".(($Listings['1'] > 1) ? '(s)':'')." in the Directory you specified";


That should output (I'm guessing the file names :)):-

1 cat.jpg
2 dog.jpg
3 rabbit.jpg
4 pig.jpg

ol will do the numbering for you, and I think that will do as you ask.

Rocknbil is absolutely right though PHP5 > is supportive of scandir - readdir is backwards compatible.

>>For some reason "$_SERVER[DOCUMENT_ROOT]" generated an error.

Worked fine for me :/ outside of the quotes it would need to be $_SERVER['DOCUMENT_ROOT']

Cheers,
MRb
4:27 pm on Jul 22, 2010 (gmt 0)

5+ Year Member



Thank you, MRb...
I've been trying to work on a line by line counting method in php because I am not echoing inside the HTML body tags and so the <ol> tag does not function. It seems to be close now except for the looping.
6:39 pm on Jul 22, 2010 (gmt 0)

WebmasterWorld Senior Member rocknbil is a WebmasterWorld Top Contributor of All Time 10+ Year Member



Ok . . well . . . you don't need to echo, you can store it in a var and echo it wherever you want. You are partly correct on the number, but count() is also counting . and ..

You're getting dupes because you're looping in a loop, as you guessed. You only need one.


$dir = 'myfolder/';
$files = scandir("$dir");
$num = 0;
$file_list=null;

foreach ($files as $file) {
if (preg_match('/\.jpe*g$/i',$file)) {
$num++;
$file_list .= "<li>$num $dir/$file</li>";
}
}
if ($file_list) { $file_list = "<ol>$file_list</ol>"; }


You can remove that last line if you don't want to use OL, which is redundant if you're doing $num. At any rate you can put this wherever you want:

echo $file_list;
12:02 am on Jul 23, 2010 (gmt 0)

5+ Year Member



Ahh...Now this worked brilliantly, Rocknbil ! The output was perfect! if I removed the "/\.jpe*g$/i" from preg_match will it read every file in the directory and include other types of image files such as .gif, .bmp, and .png or can I omit the entire line so that it reads every file in the directory?
5:38 pm on Jul 23, 2010 (gmt 0)

WebmasterWorld Senior Member rocknbil is a WebmasterWorld Top Contributor of All Time 10+ Year Member



If you want to read every file, check for file instead. But it's wisest to use the full path as I initially showed you. This should work.


$root = $_SERVER['DOCUMENT_ROOT'];
$dir = 'myfolder/';
$files = scandir("$dir");
$num = 0;
$file_list=null;
foreach ($files as $file) {
if (is_file("$root/$dir/$file")) {
$num++;
$file_list .= "<li>$num $dir/$file</li>";
}
}
if ($file_list) { $file_list = "<ol>$file_list</ol>"; }
12:13 pm on Jul 24, 2010 (gmt 0)

WebmasterWorld Senior Member 5+ Year Member



$root = $_SERVER['DOCUMENT_ROOT'];

Just a note, it is, in my opinion, worth doing this like this:
$root = rtrim($_SERVER['DOCUMENT_ROOT'], "/");

As, depending on the server set up, document_root may or may not have a trailing slash. So, make sure there isn't one at all to keep your code portable.
4:55 pm on Jul 24, 2010 (gmt 0)

WebmasterWorld Senior Member rocknbil is a WebmasterWorld Top Contributor of All Time 10+ Year Member



Though I've never seen that, it would be worth the effort . . . :-)
5:49 pm on Jul 24, 2010 (gmt 0)

WebmasterWorld Senior Member 5+ Year Member



The servers where I work have a trailing slash on root. My own personal one doesn't.

Caused a bit of annoyance when I was still doing free-lance projects from home :)
6:48 am on Jul 25, 2010 (gmt 0)

5+ Year Member



document_root may or may not have a trailing slash. So, make sure there isn't one at all to keep your code portable.

That is good advice, I've had the same troubles with the slash on end of $_SERVER['DOCUMENT_ROOT']. My localhost on WAMP has the slash at end of that, though my remote server does not, so I've always fixed it too.
 

Featured Threads

Hot Threads This Week

Hot Threads This Month