M Miller
M Miller

Reputation: 5642

Sorting a glob alphabetically, but with directories first

Using glob(), I obtained a list of files and directories within a directory.

I wanted to sort this, so I used natcasesort(). Then I wanted to place all directories first, so I used usort().

$files = glob($directory.'/*');
natcasesort($files);
usort($files, function ($a, $b) {
    return ((int) is_dir($b)) - ((int) is_dir($a));
});
var_dump($files);

The first sort worked fine, but in the second sort process, I lost my natural sorting and nothing appears to have much order. I was kind of hoping that if a sort function returns 0, it would retain the existing order, but now I'm not so sure.

How can I accomplish such a task, or do I need to manually resort the array with two foreach statements, one for directories and one for files?

Upvotes: 2

Views: 1046

Answers (1)

Iłya Bursov
Iłya Bursov

Reputation: 24146

you need to sort whole array in one step:

$files = glob($directory.'/*');
usort($files, function ($a, $b) {
    $aIsDir = is_dir($a);
    $bIsDir = is_dir($b);
    if ($aIsDir === $bIsDir)
        return strnatcasecmp($a, $b); // both are dirs or files
    elseif ($aIsDir && !$bIsDir)
        return -1; // if $a is dir - it should be before $b
    elseif (!$aIsDir && $bIsDir)
        return 1; // $b is dir, should be before $a
});
var_dump($files);

Upvotes: 3

Related Questions