PHP:首先排序文件夹,然后排序文件

时间:2013-02-25 05:03:54

标签: php sorting directory

$dir = '/master/files';
$files = scandir($dir);
foreach($files as $file){
   if(($file != '.') && ($file != '..')){
      if(is_dir($dir.'/'.$file)){
         echo '<li class="folder">'.$file.'</li>';
      }else{
         echo '<li class="file">'.$file.'</li>';
      }
   }
}

从上面的脚本中,我得到了结果:

images (folder)
index.html    
javascript (folder)
style.css

如何先对文件夹进行排序,然后对文件进行排序?

7 个答案:

答案 0 :(得分:8)

试试这个:

$dir = '/master/files';
$directories = array();
$files_list  = array();
$files = scandir($dir);
foreach($files as $file){
   if(($file != '.') && ($file != '..')){
      if(is_dir($dir.'/'.$file)){
         $directories[]  = $file;

      }else{
         $files_list[]    = $file;

      }
   }
}

foreach($directories as $directory){
   echo '<li class="folder">'.$directory.'</li>';
}
foreach($files_list as $file_list){
   echo '<li class="file">'.$file_list.'</li>';
}

答案 1 :(得分:4)

你不需要制作2个循环,你可以用这段代码完成工作:

<?php

function scandirSorted($path) {

    $sortedData = array();
    foreach(scandir($path) as $file) {

        // Skip the . and .. folder
        if($file == '.' || $file == '..')
            continue;            

        if(is_file($path . $file)) {
            // Add entry at the end of the array
            array_push($sortedData, '<li class="folder">' . $file . '</li>');
        } else {
            // Add entry at the begin of the array
            array_unshift($sortedData, '<li class="file">' . $file . '</li>');
        }
    }
    return $sortedData;
}

?>

此功能将返回路径条目列表,首先是文件夹,然后是文件。

答案 2 :(得分:3)

尽可能少地修改代码:

$folder_list = "";
$file_list = "";
$dir = '/master/files';
$files = scandir($dir);
foreach($files as $file){
   if(($file != '.') && ($file != '..')){
      if(is_dir($dir.'/'.$file)){
         $folder_list .= '<li class="folder">'.$file.'</li>';
      }else{
         $file_list .= '<li class="file">'.$file.'</li>';
      }
   }
}

print $folder_list;
print $file_list;

这只会循环一次,而不需要多次通过。

答案 3 :(得分:1)

将输出存储在2个数组中,然后遍历数组以正确的顺序输出它们。

$dir = '/master/files';

$contents = scandir($dir);

// create blank arrays to store folders and files
$folders = $files = array();

foreach ($contents as $file) {

    if (($file != '.') && ($file != '..')) {

        if (is_dir($dir.'/'.$file)) {

            // add to folders array
            $folders[] = $file;

        } else {

            // add to files array
            $files[] = $file;

        }
    }
}

// output folders
foreach ($folders as $folder) {

    echo '<li class="folder">' . $folder . '</li>';

}

// output files
foreach ($files as $file) {

    echo '<li class="file">' . $file . '</li>';

}

答案 4 :(得分:1)

我有一个N深度递归目录扫描的解决方案:

function scanRecursively($dir = "/") {
    $scan = array_diff(scandir($dir), array('.', '..');
    $tree = array();
    $queue = array();
    foreach ( $scan as $item ) 
        if ( is_file($item) ) $queue[] = $item;
        else $tree[] = scanRecursively($dir . '/' . $item);
    return array_merge($tree, $queue);
}

答案 5 :(得分:0)

尝试

<?php
    $path = $_SERVER['DOCUMENT_ROOT'];
    chdir ($path);

    $dir = array_diff (scandir ('.'), array ('.', '..', '.DS_Store', 'Thumbs.db'));

    usort ($dir, create_function ('$a,$b', '
        return  is_dir ($a)
        ? (is_dir ($b) ? strnatcasecmp ($a, $b) : -1)
        : (is_dir ($b) ? 1 : (
            strcasecmp (pathinfo ($a, PATHINFO_EXTENSION), pathinfo ($b, PATHINFO_EXTENSION)) == 0
            ? strnatcasecmp ($a, $b)
            : strcasecmp (pathinfo ($a, PATHINFO_EXTENSION), pathinfo ($b, PATHINFO_EXTENSION))
        ))
    ;
'));

    header ('content-type: text/plain');
    print_r ($dir);
?>

答案 6 :(得分:0)

作为CodeIgniter的爱好者,我实际上修改了核心 directory_helper ,除了设置深度和选择是否应该隐藏文件之外,还包括使某些文件免于扫描的能力包括在内。

  

归功于CI的原作者。我只是添加了它   使用免除数组并在排序中构建。

它使用kso​​rt对文件夹进行排序,因为文件夹名称设置为键,natsort用于命令每个文件夹中的文件。

您唯一需要做的就是为您的环境定义DIRECTORY_SEPARATOR,但我认为您不需要修改其他内容。

function directory_map($source_dir, $directory_depth = 0, $hidden = FALSE, $exempt = array())
{
    if ($fp = @opendir($source_dir))
    {
        $folddata   = array();
        $filedata   = array();
        $new_depth  = $directory_depth - 1;
        $source_dir = rtrim($source_dir, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;

        while (FALSE !== ($file = readdir($fp)))
        {
            // Remove '.', '..', and hidden files [optional]
            if ($file === '.' OR $file === '..' OR ($hidden === FALSE && $file[0] === '.'))
            {
                continue;
            }

            is_dir($source_dir.$file) && $file .= DIRECTORY_SEPARATOR;

            if (($directory_depth < 1 OR $new_depth > 0) && is_dir($source_dir.$file))
            {
                $folddata[$file] = directory_map($source_dir.$file, $new_depth, $hidden, $exempt);

            }
            elseif(empty($exempt) || !empty($exempt) && !in_array($file, $exempt))
            {
                $filedata[] = $file;
            }
        }

        !empty($folddata) ? ksort($folddata) : false;
        !empty($filedata) ? natsort($filedata) : false;

        closedir($fp);
        return array_merge($folddata, $filedata);
    }

    return FALSE;
}

用法示例如下:

$filelist = directory_map('full_server_path');

如上所述,它会将文件夹名称设置为子数组的键,因此您可以期待以下内容:

Array(
[documents/] => Array(
    [0] => 'document_a.pdf',
    [1] => 'document_b.pdf'    
    ),
[images/] => Array(
    [tn/] = Array(
        [0] => 'picture_a.jpg',
        [1] => 'picture_b.jpg'
        ),
    [0] => 'picture_a.jpg',
    [1] => 'picture_b.jpg'        
    ),
[0] => 'file_a.jpg',
[1] => 'file_b.jpg'
);

请记住,免除将应用于所有文件夹。如果您想跳过index.html文件或您不想包含的目录中使用的其他文件,这很方便。