PHP code that does not recursively traverse all files in a directory

  • 2021-07-07 06:34:18
  • OfStack

Implementation code:


/**
 * PHP  Non-recursive implementation queries all files in this directory 
 * @param unknown $dir
 * @return multitype:|multitype:string
 */
function scanfiles($dir) {
 if (! is_dir ( $dir ))
 return array ();
 
 //  Compatible with all operating systems 
 $dir = rtrim ( str_replace ( '\\', '/', $dir ), '/' ) . '/';
 
 //  Stack, the default value is the incoming directory 
 $dirs = array ( $dir );
 
 //  Container where all files are placed 
 $rt = array ();
 
 do {
 //  Bullet stack 
 $dir = array_pop ( $dirs );
 
 //  Scan the directory 
 $tmp = scandir ( $dir );
 
 foreach ( $tmp as $f ) {
  //  Filter . ..
  if ($f == '.' || $f == '..')
  continue;
  
  //  Combine the current absolute path 
  $path = $dir . $f;
  
  
  //  If it is a directory, press the stack. 
  if (is_dir ( $path )) {
  array_push ( $dirs, $path . '/' );
  } else if (is_file ( $path )) { //  If it is a file, put it in a container 
  $rt [] = $path;
  }
 }
 
 } while ( $dirs ); //  Until there are no directories in the stack 
 
 return $rt;
}

Attached another article: Do not recursively traverse the files in the directory

If you want to traverse all the files in a directory (including subdirectories), the first idea that comes to mind is to use recursion: first deal with the current directory, and then deal with the subdirectories in the current directory. Can you not recursion? When learning data structure before, I saw that recursion is actually realized by using stack. The characteristic of recursion is to call itself constantly. The last call is the first to be executed, the penultimate call is the second to be executed, and so on. The first call is the last to be executed. If you understand the principle of recursion, you can actually turn all recursive implementations into non-recursive implementations.

Traversing all files in a certain directory in a non-recursive way is mainly divided into three steps:

1. Create an array and put the directory to be traversed into; (In fact, a stack was created)
2. Loop to process this array, and the condition that the loop ends is that the array is empty;
3. Every loop, deal with one element in the array and delete the element. If this element is a directory, add all the sub-elements in the directory to the array;

The code written along this line is as follows:


/**
 *  Traverse all files in a directory 
 * @param string $dir
 */
function scanAll($dir)
{
  $list = array();
  $list[] = $dir;

  while (count($list) > 0)
  {
    // Last of the pop-up array 1 Elements 
    $file = array_pop($list);

    // Processing the current file 
    echo $file."\r\n";

    // If it is a directory 
    if (is_dir($file))
    {
      $children = scandir($file);
      foreach ($children as $child)
      {
        if ($child !== '.' && $child !== '..')
        {
          $list[] = $file.'/'.$child;
        }
      }
    }
  }
}

I don't think recursion has much disadvantage here. In fact, in many cases, it is very simple and readable to design with recursion. As for efficiency, it will only have an impact when the recursion depth is extremely large.

The following is a recursive implementation for comparison:


/**
 *  Traverse all files in a directory ( Recursive implementation )
 * @param string $dir
 */
function scanAll2($dir)
{
  echo $dir."\r\n";

  if (is_dir($dir))
  {
    $children = scandir($dir);
    foreach ($children as $child)
    {
      if ($child !== '.' && $child !== '..')
      {
        scanAll2($dir.'/'.$child);
      }
    }
  }
}

Running shows that the results of the two functions are slightly different, mainly in the order of printing. The order of running results of function 1 is reversed, because the order of pressing stacks is just opposite to that of scandir. You can change line 21 to 1:


$children = array_reverse(scandir($file));

In this way, the result is exactly the same.


Related articles: