33

I'm trying to make scandir(); function go beyond its written limits, I need more than the alpha sorting it currently supports. I need to sort the scandir(); results to be sorted by modification date.

I've tried a few solutions I found here and some other solutions from different websites, but none worked for me, so I think it's reasonable for me to post here.

What I've tried so far is this:

function scan_dir($dir)
{
    $files_array = scandir($dir);
    $img_array   = array();
    $img_dsort   = array();
    $final_array = array();

    foreach($files_array as $file)
    {
        if(($file != ".") && ($file != "..") && ($file != ".svn") && ($file != ".htaccess"))
        {
            $img_array[] = $file;
            $img_dsort[] = filemtime($dir . '/' . $file);   
        }
    }

    $merge_arrays = array_combine($img_dsort, $img_array);
    krsort($merge_arrays);

    foreach($merge_arrays as $key => $value)
    {
        $final_array[] = $value;    
    }

    return (is_array($final_array)) ? $final_array : false;
}

But, this doesn't seem to work for me, it returns 3 results only, but it should return 16 results, because there are 16 images in the folder.

halfer
  • 19,824
  • 17
  • 99
  • 186
aborted
  • 4,481
  • 14
  • 69
  • 132

4 Answers4

118
function scan_dir($dir) {
    $ignored = array('.', '..', '.svn', '.htaccess');

    $files = array();    
    foreach (scandir($dir) as $file) {
        if (in_array($file, $ignored)) continue;
        $files[$file] = filemtime($dir . '/' . $file);
    }

    arsort($files);
    $files = array_keys($files);

    return $files;
}
Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
Ryon Sherman
  • 1,553
  • 1
  • 11
  • 8
  • @dugi try this method. The file names in a single directory should be unique. Therefore, they can be used as the key. The array is then sorted by values (the modification time) and the keys (the file names) are returned in proper order. – Ryon Sherman Aug 12 '12 at 16:47
  • 3
    Works great. To ignore all dot files you can use array-like string indexing instead of in_array to check the first character of the filename: if ($file[0] === '.') continue; – Richard Jul 03 '15 at 09:10
  • 1
    you saved my app.. Thank you dear – Ramesh_D Jun 02 '18 at 11:59
8

This is a great question and Ryon Sherman’s answer provides a solid answer, but I needed a bit more flexibility for my needs so I created this newer function: better_scandir.

The goal is to allow having scandir sorting order flags work as expected; not just the reverse array sort method in Ryon’s answer. And also explicitly setting SORT_NUMERIC for the array sort since those time values are clearly numbers.

Usage is like this; just switch out SCANDIR_SORT_DESCENDING to SCANDIR_SORT_ASCENDING or even leave it empty for default:

better_scandir(<filepath goes here>, SCANDIR_SORT_DESCENDING);

And here is the function itself:

function better_scandir($dir, $sorting_order = SCANDIR_SORT_ASCENDING) {

  /****************************************************************************/
  // Roll through the scandir values.
  $files = array();
  foreach (scandir($dir, $sorting_order) as $file) {
    if ($file[0] === '.') {
      continue;
    }
    $files[$file] = filemtime($dir . '/' . $file);
  } // foreach

  /****************************************************************************/
  // Sort the files array.
  if ($sorting_order == SCANDIR_SORT_ASCENDING) {
    asort($files, SORT_NUMERIC);
  }
  else {
    arsort($files, SORT_NUMERIC);
  }

  /****************************************************************************/
  // Set the final return value.
  $ret = array_keys($files);

  /****************************************************************************/
  // Return the final value.
  return $ret;

} // better_scandir
Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
Giacomo1968
  • 25,759
  • 11
  • 71
  • 103
1

Alternative example..

$dir = "/home/novayear/public_html/backups";
chdir($dir);
array_multisort(array_map('filemtime', ($files = glob("*.{sql,php,7z}", GLOB_BRACE))), SORT_DESC, $files);
foreach($files as $filename)
{
  echo "<a>".substr($filename, 0, -4)."</a><br>"; 
}  
NovaYear
  • 167
  • 1
  • 2
  • 13
0

Another scandir keep latest 5 files:

public function checkmaxfiles()
{

    $dir = APPLICATION_PATH . '\\modules\\yourmodulename\\public\\backup\\';
    // '../notes/';
    $ignored = array('.', '..', '.svn', '.htaccess');
    $files = array();
    foreach (scandir($dir) as $file) {
        if (in_array($file, $ignored)) continue;
        $files[$file] = filemtime($dir . '/' . $file);
    }
    arsort($files);
    $files = array_keys($files);
    $length = count($files);
    if($length < 4 ){
        return;
    }
    for ($i = $length; $i > 4; $i--) {
           echo "Erase : " .$dir.$files[$i];
           unlink($dir.$files[$i]);
    }

}
Toni
  • 1,555
  • 4
  • 15
  • 23
Letech
  • 9
  • 3