views:

168

answers:

6

If you scan a folder containing other folders AND files, how do you get rid of . and .. and files? How do you put in array only folders WITHOUT . and ..? I would like to use regular expression, but I'm newbie and I can't get it right. My code is now this but doesn't work:

if(fnmatch("\.{1,2}",$dir_array[$i]) || is_file($dir_array[$i]){
unset($dir_array[$i]);
}else{ //other code
}

+9  A: 

You are confusing fnmatch and regular expressions in your code. To get all files and directories except the special ones, use this:

$dir_array = array_diff($dir_array, array(".", ".."));

Alternatively, if you iterate the array anyway, you can test each element like this:

foreach ($dir_array as $name) {
    if (($name != "..") && ($name != ".")) {
     // Do stuff on all files and directories except . ..
     if (is_dir($name)) {
         // Do stuff on directories only
     }
    }
}

In php<5.3, you can exclusively use a callback function, too:

$dir_array = array_filter($dir_array,
  create_function('$n', 'return $n != "." && $n != ".." && is_dir($n);'));

(See Allain Lalonde's answer for a more verbose version)

Since php 5.3, this can be written nicer:

$dir_array = array_filter($dir_array,
  function($n) {return $n != "." && $n != ".." && is_dir($n);});

Finally, combining array_filter and the first line of code of this answer yields an (insignificantly) slower, but probably more readable version:

$dir_array = array_filter(array_diff($dir_array, array(".", "..")), is_dir);
phihag
I didn't mean . and .. are files, I just wanted to delete these directories from array together with possible files. But I like how you used array_diff. Thanks
perfectDay
Oops, my bad. Sorry, on rereading I can't understand why I wrote it that way. I'll update the answer.
phihag
+1  A: 

You don’t need a regular expression to test this. Just use plain string comparison:

if ($dir_array[$i] == '.' || $dir_array[$i] == '..' || is_file($dir_array[$i])) {
    unset($dir_array[$i]);
}
Gumbo
+1  A: 

This may do it.

function is_not_meta_dir($file_name) {
  // return true if $filename matches some pattern.
  // without knowing the format of your $dir_array
  return $file_name != '.' && $file_name != '..';
}

$new_dir_array = array_filter($dir_array, 'is_not_meta_dir');
Allain Lalonde
That looks like lambda ... uhmmm .. create_function could beautify the code. Anyway, you should decide between $filename and $file_name ;)
phihag
typo. Dang my dependence on IDEs. Also, create_function would be an alternative to the above, but I'm not sure I'd consider it more beautiful.
Allain Lalonde
@Allain Lalonde: I agree create_function looks ugly, but I prefer it from an ivory tower point of view ;). Since 5.3, you can write array_filter($d_a, function($fn) {return $fn!="." }); which is definitely nicer.
phihag
A: 

I would do it like this:

$items = array();
$handle = opendir('path/to/dir');
while (($item = readdir($handle)) !== false) {
    if (! in_array($item, array('.', '..'))) {
        $items[] = $item;
    }
}
closedir($handle);

print_r($items);

Although, I'd rather prefer DirectoryFilterDots but it's kind of rare in the available PHP distributions.

Ionuț G. Stan
A: 

I'd do something like this (code may not work without effort since I haven't worked in PHP for years)

<?
if ($handle = opendir('/myPath')) 
  {
  while (false !== ($file = readdir($handle)))
  { 
    if (bool is_dir ( $file ) && substring($file,0,1) != ".")
      {
        $filesArray[] = $file; // this is the bit I'm not sure of the syntax for. 
      }
    }
  }
?>

EDIT misread the question - This should now add to the array all the folder names ion myPath that are not "." or ".."

ZombieSheep
+1  A: 

no regex is needed, just unset() the first two values.

$d = dir($dir);
unset($d[0]);
unset($d[1]);
Jeff Winkworth
This requires no repetitive if's or iteration and would perform the fastest, so +1 to you sir. This is as simple and clean as it gets.
Syntax
First I did it also like this, but then I thought what if . and .. are not [0] and [1]. I try to do everything as universal as possible.
perfectDay