Method for getting the newest file in a directory?

This is a difficult question to search the forum for…too many generic terms in my query, hah.

I’ve been stuck on a fairly simple question for a day or so. I want to be able to run face detection on photos as they are added to a folder. I have a program that is sequentially loading images from another outside process (downloading email attachments). Each of the files that comes in from that process is just named ‘0’ or ‘1’ ‘2’ etc etc. No extensions or anything. They just get added to an empty folder that is read by my oF program.

My program seems to work fine as long as everything goes according to plan, but I run into trouble in a few places.

First is that the ofDirectory does different file indexing than OSX does (which took me a couple hours to finally figure out, hah)…if files are 1,2,3,10…the 10 will come after 3 in OSX but before 1 in ofDirectory (10,1,2,3). I was able to get a remedy of this by just counting the files in the folder and doing an ofToString to make sure that 10 came after 9, etc. The easiest thing for me to do would be to just check what the newest file in the folder is instead of trying these workarounds.

The next problem is that if the folder gets two files in close succession then it can mess up the counting and possibly try and read a file that isn’t there.

I’m assuming there is a simple fix here, but I just have tunnelvision…here is some code of the area I’m looking at:
Update:

  
void testApp::update(){  
    numFiles=DIR.listDir("originals");  
    if (numFiles>prevNumFiles) {  
        newPic=true;  
    }  
}  
  

Draw:

  
    if (newPic) {  
          
// I use two of these jsut to keep things straight for me later  
        fileIndex = numFiles-1;  
        fileString = numFiles-1;  
        cout << "\n Current count: " << fileIndex << endl;  
          
//My idea for this part was that if I the file count is 5 and the next file is named "20" it should just jump to that instead of trying to load what is in index 5 (6-1)  
        if (fileIndex != ofToInt(DIR.getName(fileIndex)) ) {  
            fileString = ofToInt(DIR.getName(fileIndex));  
            cout << "Files aren't in order. New File Index is: " << fileString << endl;  
        }  
          
        img.loadImage("originals/"+ofToString(fileString));  
        cout << "-----" <<endl;  
        cout << "Loaded image: " << fileString << endl;  

regarding files being ‘out of order’, this can be fixed with ofDirectory::sort() after you’ve called listDir(). i believe they’re out of order for backwards compatibility and for cross-OS compatibility. something i see from zach+theo a lot is using 0-padded filenames.

i think if you use one of these solutions (sort() or 0-padding) that should get rid of your other problem.

Ah ha…the zero padding seems to work for now, thanks! That bug was driving me crazy but that’s an easy fix…might try sort too in case I see anything other advantages…seems like i would have to get into other libraries to be able to access the newest file or the most recently modified…or just store an array of what’s there and compare and see if it’s a repeat or something

Ages ago I wrote a version of ofxDirList that uses Poco to do the file listing. I use it to do recursive directory listing mostly, but I also hooked up date created, date modified, size etc so you can check creation time.

The API is backwards compatible so you can drop it in as a replacement to ofxDirList really easy and then use a call to getCreated(int pos) to get the date created.

You can find goDirList at https://github.com/gameoverhack/goDirList

@gameover, i rewrote the 007 ofxDirList to use Poco, and then it was turned into ofDirectory. now you can use ofDirectory::getFile() to get an ofFile, and ofFile::getPocoFile() will give you a Poco file that has created(), getLastModified() etc.

having a sort-by method in ofDirectory would be nice. right now you would need to make a special container and use STL directly.

I have used a solution on Java, don’t know if that helps you :D. Basically you create an app with this library (JNotify) whenever you get a change on the directory it sends the change through OSC to the OF app :slight_smile:

@kylemcdonald @arturo

Poco::File &filepoco = file.getPocoFile();

In oF 0.9.0 it seems no longer to work. I get two errors for this line:

No type named ‘File’ in namespace ‘Poco’
No member named ‘getPocoFile’ in ‘ofFile’

Do you know how to get a Poco file? Actually I just need the timestamp via Poco::File getLastModified().

=)

in 0.9 we don’t use Poco any more instead we are using boost filesystem which will become std soon, the way to do this now is:

std::filesystem::last_write_time(file);

where file is an ofFile, ofDirectory

3 Likes

Hi,

I’m rather newbie, and hoping to prototype a ui for exploring some media I’ve taken. I’d like to have a timeline representing the creation date of files, where the x-axis is the date. One row would be images, and the other video, where the duration of the video is representing by the width of the image(s) object.

For starters I’m just wanted some help to read the creation date and map it to the x position. I see the ofFile line above but have tried a few things, just getting errors. Help!

Basically, all I’ve done so far is draw an image, and some text representing fake dates.

perhaps if you post what you are trying and the error you are getting it would be easier. in general using the above call you can get the last modification date of a file so comparing those dates you can order the files by date and even know how far apart in time they are

Hi Arturo i’m using that code but im getting an error:

std::filesystem::last_write_time( dir.getName(1) );

libc++abi.dylib: terminating with uncaught exception of type boost::filesystem::filesystem_error: boost::filesystem::last_write_time: No such file or directory: “Saved Data_CSV File preview.png”

you need to be a bit more careful when accessing arrays… using 1 directly is a bad idea,
also not sure what you pass qualifies as a valid file

try smthng like:

ofFile itm;
if(itm.exists()&&!itm.isDirectory())
time_t date = std::filesystem::last_write_time(itm);