How to sort the contents of a directory alphabetically with sub directorys appearing before normal files?

110 views Asked by At

I need to sort the contents of a directory in ascending order (alphabetically). The directories must appear before files even if the directory's name would appear after a files name (alphabetically). The same way file explorers do, they list directories sorted then they list the files sorted.

I am using the following code which gives me a sorted list alphabetically but it does not advances the directories first:

if($handler = opendir($dir))
{
    while (($sub = readdir($handler)) !== FALSE)
    {
        // ...
    }    
    closedir($handler); 
}
2

There are 2 answers

1
georg On BEST ANSWER

A straightforward way to achieve that would be to populate an array with pairs like [is_file(path), path], sort this array (php will automatically sort by the first and then by the second element) and finally remove the is_file bit:

$path = 'somedir';
$dir = [];

// populate
foreach(glob("$path/*") as $f)
    $dir []= [is_file($f), $f];

// sort
sort($dir);

// remove
$dir = array_map('end', $dir);

// PROFIT
print_r($dir);
0
robbmj On

Something like this should work

$contents = array();
while (($sub = readdir($handler)) !== FALSE) {
    if ($sub !== '.' && $sub !== '..') {
        $contents[] = array('is_dir' => is_dir($sub), 'name' => $sub);
    }    
}   

closedir($handler); 

usort($contents, function($a, $b) {
    if ($a['is_dir'] && !$b['is_dir']) {
        return -1;
    }
    else if (!$a['is_dir'] && $b['is_dir']) {
        return 1;
    }
    // they are either both files or both directories
    else {
        return strcmp($a['name'], $b['name']);
    }
});

foreach ($contents as $c) { 
    echo $c['name'] . PHP_EOL; 
}

Tested with the following directory (directories don't have extensions):

ls
1  findp.php  fooo  simple_html_dom.php  test  test.txt 

Output:

1
fooo
test
findp.php
simple_html_dom.php
test.txt