【问题标题】:PHP: sort folder first and then filesPHP:首先对文件夹进行排序,然后对文件进行排序
【发布时间】:2013-02-10 05:05:18
【问题描述】:
$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

如何先对文件夹排序再对文件排序?

【问题讨论】:

  • 首先将它们保存在两个数组中,然后打印它们(先是文件夹,然后是文件):)
  • 你的意思是我必须做两个“foreach”?一个用于文件夹,然后用于文件?

标签: php sorting directory


【解决方案1】:

试试这个:

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

【讨论】:

  • 我觉得两个foreach不好,创建数组的时候保存li,然后用implode打印比较好
【解决方案2】:

你不需要做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;
}

?>

此函数将返回您的路径条目列表,首先是文件夹,然后是文件。

【讨论】:

  • 循环样式是个好主意,但这不会对文件夹或文件进行排序a-z order。
  • 确实,如果顺序很重要,那么你必须使用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;

这只循环遍历所有内容一次,而不需要多次遍历。

【讨论】:

    【解决方案4】:

    我有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】:

      将输出存储在 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>';
      
      }
      

      【讨论】:

        【解决方案6】:

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

        所有功劳归 CI 的原作者所有。我只是添加到它 使用豁免数组并在排序中构建。

        它使用 ksort 对文件夹进行排序,因为文件夹名称被设置为键,而 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 文件或在您不想包含的目录中使用的其他文件,这很方便。

        【讨论】:

          【解决方案7】:

          试试

          <?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);
          ?>
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-04-06
            • 1970-01-01
            • 2021-12-28
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多