PHP readdir is not reading some files - php

I'm using the following code to loop through a directory to print out the names of the files. However, not all of the files are displayed. I have tried using clearstatcache with no effect.
$str = '';
$ignore = array('.', '..');
$dh = #opendir( $path );
if ($dh === FALSE)
{
// error
}
$file = readdir( $dh );
while( $file !== FALSE )
{
if (in_array($file, $ignore, TRUE)) { break; }
$str .= $file."\n";
$file = readdir( $dh );
}
Here's the contents of the directory right now:
root.auth test1.auth test2.auth test3.auth test5.auth
However, test5.auth does not appear. If I rename it to test4.auth it does not appear. If I rename it to test6.auth it does appear. This is reliable behaviour - I can rename it several times and it still won't show up unless I rename it to test6.auth.
What on earth could be happening?
I'm running Arch Linux (kernel 2.6.26-ARCH) with PHP Version 5.2.6 and Apache/2.2.9 with Suhosin-Patch. My filesystem is ext3 and I'm running fam 2.6.10.

Continue won't work either, because you will skip the line that reads the next file.
You could get rid of the first $file = readdir( $dh ); and then do
while (false !== ($file = readdir($dh))) {
if (in_array($file, $ignore, TRUE)) { continue; }
$str .= $file."\n";
}

Your break keywords messes up your code:
Your loop very likely first encounters the '.' directory and than breaks out of your while loop.
try replacing it with a continue and you should be fine.

if (in_array($file, $ignore, TRUE)) { break; }
Surely that should be continue not break?

Related

readdir() in php not seeming to work

I'm working on the following piece of code:
<?php
$dir=opendir("docs/recipes");
$files=array();
while (($file=readdir($dir)) !== false)
{
if ($file != "." and $file != ".." and $file != "index.php")
{
array_push($files, $file);
}
}
closedir($dir);
sort($files,SORT_STRING | SORT_FLAG_CASE);
print "<div class=\"blocktext\">";
foreach ($files as $file)
print "$file<br>";
print "</div>";
?>
I had this working on my raspberry pi web server, but I moved my server to arch linux, and it doesn't seem to be working. When I load the page, it spins but then the list of files is empty.
I have checked that httpd is running with systemd and because my webpages load. I know php is working because my phpinfo test page works.
In the folder containing this file, I have a symbolic link called docs, and I know the path is correct. I have all the files in the destination readable. This file is executable.
Is there something else I am missing?
Not necessarily a solution, but some help with good practices and a way to find what is happening on your script
<?php
// initialize variables first
$dir = false;
$files = array();
// assign the handler
$dir = opendir( "docs/recipes" );
// work only if necessary
if ( $dir !== false ) {
while ( ( $file = readdir( $dir ) ) !== false ) {
if ($file != "." and $file != ".." and $file != "index.php") {
array_push($files, $file);
}
}
closedir( $dir );
sort( $files,SORT_STRING | SORT_FLAG_CASE );
print "<div class=\"blocktext\">";
foreach ( $files as $file ) {
print "$file<br>";
}
print "</div>";
} else {
// get informed that something is wrong, print anything that helps you
echo( 'problems opening' );
exit( __FILE__.' '.__LINE__ );
}
?>
from php.net/readdir comes a warning: This function may return Boolean FALSE, but may also return a non-Boolean value which evaluates to FALSE.
you have not specified which version of PHP you are using, nor if it's installed/compiled locally. it would help. my guess is that you don't have all errors turned on, and readdir is catching one of those corner cases.
try this:
$cycle = true;
while ( $cycle !== false ) {
$file = readdir( $dir );
print ( "GOT a FILe or a FALSE:". $file ."br>" );
// do your stuff here
$cycle = $file;
}
then in php.ini set the errors to E_ALL. if using PHP >= 5.4 (i guess you are, since you're on arch :) you can fire up the built-in server, so all errors/logs/messages go straight to STDERR. just do a command from the folder where your index.php is located:
$ php -S <local ip>:<some port>
open as usual in the browser (or a curl, or whatever). output goes to browser, errors go straight to console, no middle-man to cover up any message.
this should enable you to catch the real problem. and/or, you can wrap it all up in a try-catch and see if something pops up.

PHP delete script not functioning

I have a script (got it from somewhere here in StackOverflow, credits don't go to me!) to
delete a folder + its contents. However, it's not working for me. After deleting the folder a record from my DB should be erased and this happens just fine. However, the folder doesn't get deleted and neither its contents! This is my code:
<?php
$filepath = dirname(__FILE__);
$gemeented = preg_replace( '#^(.*)/(.*?)/(.*?)/(.*?)/(.*?)/(.*?)$#', "$2", $filepath );
$plaatsd = preg_replace( '#^(.*)/(.*?)/(.*?)/(.*?)/(.*?)/(.*?)$#', "$4", $filepath );
$hrubriekd = preg_replace( '#^(.*)/(.*?)/(.*?)/(.*?)/(.*?)/(.*?)$#', "$5", $filepath );
$bedrijfn = preg_replace( '#^(.*)/(.*?)/(.*?)/(.*?)/(.*?)/(.*?)$#', "$6", $filepath );
$filepath2 = "http://".$gemeented.".url.nl/".$plaatsd."/".$hrubriekd."/".$bedrijfn."/";
$filepath3 = "http://".$gemeented.".url.nl/".$plaatsd."/".$bedrijfn."/";
echo $filepath2;
function Delete($filepath2)
{
if (is_dir($filepath2) === true)
{
$files = array_diff(scandir($filepath2), array('.', '..'));
foreach ($files as $file)
{
Delete(realpath($filepath2) . '/' . $file);
}
return rmdir($filepath2);
}
else if (is_file($filepath2) === true)
{
return unlink($filepath2);
}
return false;
}
?>
To make sure my $filepath2 is correct I echoed it, the result is:
http://dongen.mydomain.nl/s-gravenmoer/aandrijvingenenbesturingen/bedrijfsnaam/
That's exactly the folder I want gone, however, it ain't happening! Folder has CHMOD 755.
EDIT:
Just using $filepath won't work either, echo-ing that gives me:
/vhosts/mydomain.nl/subdomains/dongen/httpdocs/s-gravenmoer/aandrijvingenenbesturingen/bedrijfsnaam
I wasn't able to get the above script working, but I managed to find another script which works for me! Just enter the relative path and that's it!
$dirname = "../".$bedrijfn."/";
delete_directory($dirname);
function delete_directory($dirname) {
if (is_dir($dirname))
$dir_handle = opendir($dirname);
if (!$dir_handle)
return false;
while($file = readdir($dir_handle)) {
if ($file != "." && $file != "..") {
if (!is_dir($dirname."/".$file))
unlink($dirname."/".$file);
else
delete_directory($dirname.'/'.$file);
}
}
closedir($dir_handle);
rmdir($dirname);
return true;
}
Hope it helps somebody out!
Sander
You can't use url to delete files, you should give unlink a filesystem path.
(Edit: the same goes for rmdir)

is_dir() fails while scanning a directory in php

I'm trying to build a <ul> list with a <li> for each directory in a main folder.
here's my code :
<?php
$dir = opendir(getEnv("DOCUMENT_ROOT") . "/folder");
while(($file = readdir($dir)) !== false ){
if( is_dir($file) && $file !== "." && $file !== ".." ){
echo "<li>" . $file . "</li>";
}
}
closedir($dir);
?>
there are two directories in /home/example/folder but there are not recognized as folders (for sure they are !)
if I "echo" the files in the while loop they are printed (they well exist for the script no trouble on that side).
If I try to "filetype" them, a lstat failed error is thrown, I searched on internet the meaning of it and I end up with nothing but technically support that I pain to understand.
Your problem is that inside "folder" directory you can have two directories (a and b),then the reading retrieve "a" and "b" as file names, while is_dir receive a full path filename or a relative filename, you have two options:
pass the full path to filename to the is_dir function (see example code).
pass the relative path (depends on where you put your script).
if( is_dir($dir . "/" . $file) && $file !== "." && $file !== ".." ){ ......
Try:
while($file = readdir($dir)) {
if (...) { }
}
The !== false portion is not required. if readdir reaches the end, it returns a false, and the loop will automatically terminate. Your version is being parsed as:
$file gets the value of (readdir($file) is not false)
e.g. you're assigning the boolean result of readdir($file) !== false, not the return value from readdir.
to expand on my comment below, regarding operator precedence:
PHP's parse tree of your loop setup looks like this, expanded:
$bool = (readdir($dir) !== false);
$file = $bool;
To fix this, either remove the !== false portion entirely, or enforce your own precedence with extra brackets:
($file = readdir($dir)) !== false

Why does opendir not show folders with a single integer as the name

I have a script that opens a directory, checks if the folders matches an array, and then opens them.
In the directory there is a list of folders like "apache2-50", but when the script opens that folder, it only displays the .DS_Store file. Here is the output:
This-is-not-a-MacBook:backend code archangel$ php -f frolic.php "/Users/archangel/Desktop/Httpbench Files/results"
Test Found apache2 in directory /Users/archangel/Desktop/Httpbench Files/results/apache2-50
--/Users/archangel/Desktop/Httpbench Files/results/apache2-50/.DS_Store
But here is the directory listing:
This-is-not-a-MacBook:apache2-50 archangel$ ls
0 1 2
Now what I am trying to figure out why my php script is not showing those folders. When I change the folder "0" to "3" it works:
This-is-not-a-MacBook:apache2-50 archangel$ ls
1 2 3
This-is-not-a-MacBook:backend code archangel$ php -f frolic.php "/Users/archangel/Desktop/Httpbench Files/results"
Test Found apache2 in directory /Users/archangel/Desktop/Httpbench Files/results/apache2-50
--/Users/archangel/Desktop/Httpbench Files/results/apache2-50/.DS_Store
--/Users/archangel/Desktop/Httpbench Files/results/apache2-50/1
--/Users/archangel/Desktop/Httpbench Files/results/apache2-50/2
--/Users/archangel/Desktop/Httpbench Files/results/apache2-50/3
Here is the code that I am running:
#!/bin/php
//...
$dir = opendir($argv[1]);
//Opened the directory;
while($file = readdir($dir)){
//Loops through all the files/directories in our directory;
if($file!="." && $file != ".."){
$f = explode("-", $file);
if(in_array($f[0], $servers) and in_array($f[1], $tests)) {
echo "Test Found $f[0] in directory $argv[1]/$f[0]-$f[1]\n";
$sdir = opendir("$argv[1]/$f[0]-$f[1]");
while($sfile = readdir($sdir)){
if($sfile!="." && $sfile != ".."){
echo "--$argv[1]/$f[0]-$f[1]/$sfile\n";
}
}
}
}
}
Could this be something wong with my script, or a bug in php(PHP 5.3.3)?
Thanks
This is a (very nasty) side effect of the string "0" evaluating to false in PHP. When that happens, your while loop
while($file = readdir($dir))
will break.
This should work, because it breaks only when readdir() actually returns false:
while(($file = readdir($dir)) !== false)
(obviously, change both loops accordingly, not just the outer one.)
Why are you using opendir at all? I think glob would be a little easier to use:
$files = glob("$argv[1]/*-*/*");
foreach($files as $file) {
$parts = explode("/", $file);
// get the directory part
$f = explode("-", $parts[count($parts) - 2]);
if(in_array($f[0], $servers) and in_array($f[1], $tests)) {
echo "Test Found $f[0] in directory $argv[1]/$f[0]-$f[1]\n";
echo "--$argv[1]/$f[0]-$f[1]/$sfile\n";
}
}
Replace
while($sfile = readdir($sdir)){
with
while(($sfile = readdir($sdir)) !== 0){
Otherwise when filename is 0, $sfile is "0" which is translated to false. By using !== or === you are forcing a type check between the variables so that "0" does not equal 0.

RealPath returns an empty string

I have the following which just loops through the files in a directory and echo the file names. However, when I use realpath, it returns nothing. What am I doing wrong:
if ($handle = opendir($font_path)) {
while (false !== ($file = readdir($handle))) {
if ($file != "." && $file != ".." && $file != "a.zip") {
echo $file.'<br />';//i can see file names fine
echo realpath($file);// return empty string?!
}
}
closedir($handle);
}
Thanks all for any help on this.
~I am on a windows machine, running php 5.3 and apache 2.2.
You want to use
echo realpath($font_path . DIRECTORY_SEPARATOR . $file);
else it will look in the current working dir.

Categories