28

I have an array I'm getting back from scandir, but it contains "." and ".." and I don't want it to.

My code:

$indir = scandir('../pages');
$fileextensions = array(".", "php", "html", "htm", "shtml");
$replaceextensions = str_replace($fileextensions, "", $indir);

I am doing a string replace on the file extensions, thus causing [0] and [1] to appear empty, but they are "." and ".."

array(4) {
[0]=>
string(0) ""
[1]=>
string(0) ""
[2]=>
string(4) "test"
[3]=>
string(4) "home"
}

How would I remove the "." and ".." from the array?

Mark Amery
  • 127,031
  • 74
  • 384
  • 431
Rbn
  • 371
  • 2
  • 4
  • 11
  • Related, and perhaps what you're really looking for: [Exclude hidden files from scandir](http://stackoverflow.com/questions/8532569/exclude-hidden-files-from-scandir) – Mark Amery Jun 09 '15 at 11:09

7 Answers7

44

You can use array_filter.

$indir = array_filter(scandir('../pages'), function($item) {
    return !is_dir('../pages/' . $item);
});

Note this filters out all directories and leaves only files and symlinks. If you really want to only exclude only files (and directories) starting with ., then you could do something like:

$indir = array_filter(scandir('../pages'), function($item) {
    return $item[0] !== '.';
});
leftclickben
  • 4,434
  • 21
  • 24
  • 2
    Awesome. Perfect explanation. Thanks so much. – Rbn Feb 04 '13 at 04:05
  • Don't use array_filter with a callback for this, just use `array_diff`. – Arnold Daniels Feb 04 '13 at 04:08
  • @ArnoldDaniels That would only work to remove exactly `.` and `..`, my solutions are more generalised and neither can be done with `array_diff()` – leftclickben Feb 04 '13 at 04:11
  • @leftclickben Removing `.` and `..` is exactly his question. – Arnold Daniels Feb 04 '13 at 04:14
  • 1
    Just because a junior programmer thinks they are only looking for `.` and `..`, in my experience that is rarely the case. The question states that he is putting names of files into a database. Therefore my first answer was to filter out the directories, which includes `.` and `..`. – leftclickben Feb 04 '13 at 04:23
  • Also, why do you say "don't use array_filter.. for this"? What is your reason for telling me not to using it? – leftclickben Feb 04 '13 at 04:23
28

Fastest way to remove dots as files in scandir

$files = array_slice(scandir('/path/to/directory/'), 2); 

From the PHP Manual

mintedsky
  • 1,033
  • 13
  • 18
  • 3
    This is just what I was looking for. Easy straight forward. This should be considered as best answer – Rusty Jun 20 '16 at 18:20
  • yeah seems like the best approach, seems like there should be an included filter for scan_dir built in. Seems like a no-brainer. I could be wrong. – vikingben Dec 07 '18 at 20:13
  • 1
    Taken from a [comment](https://www.php.net/manual/en/function.scandir.php#122438) on the PHP site itself: Someone wrote that array_slice could be used to quickly remove directory entries "." and "..". However, "-" is a valid entry that would come before those, so array_slice would remove the wrong entries. – Max Oct 21 '19 at 09:15
  • 2
    Never ever saw a "-" in my directory. I think in most cases this will work fine. – mintedsky Oct 22 '19 at 15:09
  • This solution does not work if you have a prefix '#' or '-' in your entries, because they go before the dot entries. – Zelkovar Feb 02 '22 at 07:36
9

array_diff will do what you're looking for:

$indir = scandir('../pages');
$fileextensions = array(".", "php", "html", "htm", "shtml");
$indir = array_diff($indir, array('.', '..'));
$replaceextensions = str_replace($fileextensions, "", $indir);

http://php.net/manual/en/function.array-diff.php

Jonathan Wren
  • 3,602
  • 22
  • 28
3

I am aware erknrio provided an answer for this, but here is a cleaner way of getting an array of files without directories (modified to be more efficient):

$dirPath = 'dashboard';

$dir = scandir($dirPath);

foreach($dir as $index => &$item)
{
    if(is_dir($dirPath. '/' . $item))
    {
        unset($dir[$index]);
    }
}

$dir = array_values($dir);
FluorescentGreen5
  • 829
  • 11
  • 23
0

You can use this snippet. It returns just files in directory:

function only_files($dir_element) {
    if (!is_dir($dir_element)) {
        return $dir_element;
    }
}

function givemefiles($dir) {
    $scanned_dir = scandir($dir);
    return array_filter($scanned_dir, "only_files");
}

$dir_path = '../pages';

givemefiles($dir_path);
echo "<pre>";
var_dump($scanned_dir);
echo "</pre>";
mrroot5
  • 1,581
  • 3
  • 24
  • 30
0

simply use preg_replace to remove all kind of hidden's file from directory

$files = array(".", "..", "html", ".~html", "shtml");    
$newfiles = preg_grep('/^([^.])/', scandir($files));
Devdutt Sharma
  • 381
  • 1
  • 2
  • 10
0

If you need a clean function;

function getFiles($dir){
    return array_values(array_filter(scandir($dir), function($file){
        global $dir;
        return !is_dir("{$dir}/{$file}");
    }));
}

I think this function is both neat and will work well. Also, the keys of the returned array in this function are sorted correctly.

Emrah Tuncel
  • 590
  • 5
  • 13