Как отсортировать содержимое каталога в алфавитном порядке с подкаталогами, появляющимися перед обычными файлами?

Мне нужно отсортировать содержимое каталога в порядке возрастания (в алфавитном порядке). Каталоги должны стоять перед файлами, даже если имя каталога будет стоять после имени файла (в алфавитном порядке). Точно так же, как файловые менеджеры, они перечисляют отсортированные каталоги, а затем отсортированные файлы.

Я использую следующий код, который дает мне отсортированный список в алфавитном порядке, но сначала не продвигает каталоги:

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

person user2155873    schedule 16.11.2014    source источник


Ответы (2)


Простой способ добиться этого — заполнить массив парами вроде [is_file(path), path], отсортировать этот массив (php будет автоматически сортировать по первому, а затем по второму элементу) и, наконец, удалить бит is_file:

$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);
person georg    schedule 16.11.2014
comment
Круто, я не знал, что sort работает для значений массива без масштабирования. - person robbmj; 17.11.2014

Что-то вроде этого должно работать

$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; 
}

Протестировано со следующим каталогом (каталоги не имеют расширений):

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

Выход:

1
fooo
test
findp.php
simple_html_dom.php
test.txt
person robbmj    schedule 16.11.2014