1. Advertising
    y u no do it?

    Advertising (learn more)

    Advertise virtually anything here, with CPM banner ads, CPM email ads and CPC contextual links. You can target relevant areas of the site and show ads based on geographical location of the user if you wish.

    Starts at just $1 per CPM or $0.10 per CPC.

Search for newest directory

Discussion in 'PHP' started by thesurface, Jul 13, 2015.

  1. #1
    Hello how can i modify this script to search in all subdirectories to get only one new directory? THX!



    This little script only search in current $path for newest directory but i also need to search in all subdirectories

    
    <?php
    function getNewestDir($path) {
    $working_dir = getcwd();
    chdir($path); ## chdir to requested dir
    $ret_val = false;
    if ($p = opendir($path) ) {
    while (false !== ($file = readdir($p))) {
    if ($file{0} != '.' && is_dir($file)) {
    $list[] = date('YmdHis', filemtime($path.'/'.$file)).$path.'/'.$file;
    }
    }
    rsort($list);
    $ret_val = $list[0];
    }
    chdir($working_dir); ## chdir back to script's dir
    return $ret_val;
    } 
    
    ?>
    
    Code (markup):
     
    thesurface, Jul 13, 2015 IP
  2. PoPSiCLe

    PoPSiCLe Illustrious Member

    Messages:
    4,623
    Likes Received:
    725
    Best Answers:
    152
    Trophy Points:
    470
    #2
    Here's a rewritten function that should work, using PHP's built-in functions:
    
    <?php
    function getNewestDir($directory) {
       $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory));
       while($it->valid()) {
         if (!$it->isDot()) {
           if (is_dir($it->getSubPath())) {
             $list[] = date('Y m d H:i:s ', filemtime($it->getSubPath())).$it->getSubPath();
           }
        }
         $it->next();
       }
       rsort($list);
       return $list[0];
    }
    
    echo getNewestDir(getcwd()); //output the latest updated directory
    
    ?>
    
    PHP:
     
    PoPSiCLe, Jul 14, 2015 IP
  3. thesurface

    thesurface Active Member

    Messages:
    260
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    73
    #3
    Thx but

    PHP Warning: rsort() expects parameter 1 to be array, null given in test.php on line 12

    line 12 is rsort($list);
     
    thesurface, Jul 14, 2015 IP
  4. PoPSiCLe

    PoPSiCLe Illustrious Member

    Messages:
    4,623
    Likes Received:
    725
    Best Answers:
    152
    Trophy Points:
    470
    #4
    Oh, yes, I didn't make it return empty if there's nothing to find - here's an ammended version which actually returns something even if there are no directories:
    
    <?php
    function getNewestDir($directory) {
       $list = '';
       $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory));
       while($it->valid()) {
         if (!$it->isDot()) {
           if (is_dir($it->getSubPath())) {
             $list[] = date('Y m d H:i:s ', filemtime($it->getSubPath())).$it->getSubPath();
           }
        }
         $it->next();
       }
       if (is_array($list)) {
         rsort($list);
         return $list[0];     
       } else {
         return 'No directories found';
       }
    }
    
    echo getNewestDir(getcwd());
    
    ?>
    
    PHP:
     
    PoPSiCLe, Jul 14, 2015 IP
  5. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #5
    Well, that seems convoluted...

    1) make it return boolean false, not a string that could be a legitimate filename. === FTMFW

    2) Why waste memory making the huge array when you could just iterate them comparing ONE value?

    3) filemTime is a 32 or 64 bit integer, so why dick with converting it to a STRING of all things?!?

    4) should probably be asking if you want the newest file (created) or most recently updated (modified) -- two different functions. Make a great optional parameter.

    5) recursion == even bigger steaming pile of /FAIL/ in terms of efficiency, particularly on something this simple.

    function getNewestDir($directory, $modified = false) {
    	$newestTime = 0;
    	$newestFile = false;
    	$d = dir($directory);
    	while (false !== $entry = $d->read()) {
    		if (
    			$d->isDir() &&
    			(($name = $d->getFilename()) != '.') &&	($name != '..') &&
    			(($time = $modified ? $d->getMTime() : $d->getCTime()) > $newestTime)
    		) {
    			$newestFile = $name;
    			$newestTime = $time;
    		}
    	}
    	return $newestFile;
    }
    Code (markup):
    Should be faster, use less memory, and returns either the name or a BOOLEAN false... also filtering out the stupid *nix "." and ".." linsux names.

    Mind you that's untested, might have a typo, but the concept is sound.

    -- edit -- side note, just LOVE how posix compliant file handling is pathetically crippled on things like filtering by type or having the OS sort for you compared to DOS 2.0!
     
    deathshadow, Jul 14, 2015 IP
  6. PoPSiCLe

    PoPSiCLe Illustrious Member

    Messages:
    4,623
    Likes Received:
    725
    Best Answers:
    152
    Trophy Points:
    470
    #6
    The concept might be sound, but it returns errors - call to undefined method isDir() and getFilename() - I haven't really looked into it, I don't have the energy right now, but the code, as presented, doesn't work.

    Running on PHP 5.5.12
     
    PoPSiCLe, Jul 14, 2015 IP
  7. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #7
    Hmm... ok, is it just me or did they just totally SCREW php.net? The site is different and nothing is documented as good as it was... Examples gone..

    I was operating partly from memory, but now the site doesn't even resemble what I was looking at just a few hours ago... since when does DIR not return a DirectoryIterator?!?

    I must be switching languages too often or something...

    function getNewestDir($directory, $modified = false) {
    	$newestTime = 0;
    	$newestFile = false;
    	$d = new DirectoryIterator($directory);
    	foreach ($d as $fileInfo) {
    		if (
    			$fileInfo->isDir() && !$fileInfo->isDot() &&
    			(($time = $modified ? $fileInfo->getMTime() : $fileInfo->getCTime()) > $newestTime)
    		) {
    			$newestFile = $d->getFilename();
    			$newestTime = $time;
    		}
    	}
    	return $newestFile;
    }
    Code (markup):
    Though I thought there was a third iterator type, one where you did WHILE and the next() method returned boolean false... At that point if you can foreach it, you might as well use glob...

    STILL nonsense you can't filter by attribute or sort at the OS level before retrieval, simple stuff you could do on CP/M in 1974. But sure, Posix is SO superior.

    -- edit -- added using isDot() meaning we don't need to dick with $name or even touch the name until we have a 'hit' -- been WAY too long since I looked at this part of the documentation. New site layout isn't helping.
     
    Last edited: Jul 14, 2015
    deathshadow, Jul 14, 2015 IP