How to determine 'Date Modified' for a folder

Is there any way in which Panorama X can access the "Date Modified’ value for a folder? Failing that, is there a UNIX command that will do it?

I need to compare the modification dates of current files and folders with those of a set of backup files and folders to determine which of the latter should be replaced by the former when I close a master database. Although, I may yet resort to the blunt instrument approach of replacing everything because I have just discovered that, when the contents of folder A are modified, that folder’s modification date changes but the date for folder B which contains folder A doesn’t change. This strikes me as being counter-intuitive but I guess it depends on how you define ‘modification’.

Which suggests an amendment to my initial question - is there perhaps a UNIX command that will return the most recent date on which anything within a folder has been changed, even at many sub-levels below the top?

OK, I’ve just discovered the copynewerfolder statement but I’m having trouble working out whether it will do the job or not. This statement:

copynewerfolder "/Sundry docs/Neighbours/Louise's farm management/Farm Management System Files/Reports/", "/Volumes/System files backup/Reports/"!

produces this error message :

CopyFile error: The file “Louise V - Jan-May2019.xlsx” doesn’t exist.  

which is odd because that file exists in both folders and is the first file in the first sub-folder of the folder being tested.

That is exceedingly odd. I don’t suppose it will mean much to you, but here is the Objective-C source code the performs the copy and generates the error message if there is one.

[fileManager copyItemAtURL:originalFileURL toURL:newFileURL error:&fileERROR];
if (fileERROR) {
    [procStack handleProcedureError:[NSString stringWithFormat:@"CopyFile error: %@",[fileERROR localizedDescription]]];
    return;
}

The copyItemAtURL method is Apple’s code. Apple’s code is doing the copy, and generating the error message (except for CopyFile error:). The localizedDescription method convert from Apple’s internal error structure into the user’s language, in this case English. If you really want to take a deep dive, here’s Apple’s documentation for the copyItemAtURL method. I doubt it will help you – it didn’t help me!

https://developer.apple.com/documentation/foundation/nsfilemanager/1412957-copyitematurl?language=objc

My guess is that there is really some other problem going on here, perhaps a permission error that is preventing access or copying, and the copyItemAtURL method is not reporting the correct error, which is unfortunate. I would recommend taking a very close look at that file and it’s metadata. Or maybe there is some permission problem with one of the enclosing folders.

As John McEnroe would say, you can’t be serious! If it didn’t help you it’s not worth a crumpet to me!!

The problem is surely not permissions - the same procedure uses the copyfile statement to move files between those same two folders. Just in case, I used GetInfo and set all permissions of the relevant folders, volumes and files to ‘Read & write’ and it made no difference. I then removed the offending file and got the same result with the next one down.

Does the statement work as advertised for you?

Don’t know of any problems with it. But I don’t have time to try it right now. Time for sleep.

Michael, maybe you have already found a better solution with the copynewerfolder statement, but the answer to your question is: Yes, the folderinfo( function works with files and folders and creates an array of information. In the 5th line of the array you find the modification date. So you can grab and handle the modification date with code like this

datepattern(nthline(fileinfo("~/image.jpg"),5),"Month ddnth, yyyy")

This is shell script is suppose to return the unix timestamp for the most recent file, folder or subfolder of the given path down to any level deep. The unix timestamp is the number of seconds since Jan. 1st, 1970 at 00:00:00 GMT. I then converted this to a standard date (not adjusting for local time zones).

let modDate=shellscript(|||find /Sundry\ docs/Neighbours/Louise's\ farm\ management/Farm\ Management\ System\ Files/Reports/ -exec stat -f "%m" \{} \; | sort -n -r | head -1|||)
modDate=superdatepattern(superdate(date("1/1/1970"),0)+modDate,"Month ddnth, yyyy","")

The unix timestamp will by itself give you a relative indication of which folder is most current.

That looks perfect Kurt but I have no folderinfo( function in my Help wizard - only the folderinfo statement which “calculates the total size of a folder, and the number of files in the folder”. What is the format of the function?

Coming back to the copynewerfolder statement, further testing leads me to believe that it doesn’t work - Could somebody please check this?

Sorry, Michael, my fault. It is not a function, it is a statement.

I created two folders with 15 files. In the destination folder, I changed the modification date of 10 files to a date one month ago. In my test, copynewerfolder always ended with an error message about a missing file, while it was definitively existing in both folders.

I then used a loop to use copynewerfile on some of my (sequentially named) 15 files. The copynewerfile loop worked flawlessly.

This line of code in copynewerfolder might be a bug:

if fileexists(folder(filepath(sfile)),filename(sfile))

This file always exists, if there are files in the source folder at all. I think this code should instead compare if the source file exists in the destination folder, too. So it should make sure to compare identical files only — independent from their sequential order. Would copynewerfolder work with a different number of files in both folders?

Looking at this code, I don’t see how it ever worked. And the code is basically unchanged from Panorama 6, so I don’t think it ever worked there either.

Since this is not a core database feature, and apparently no one has cared for ten years up until now, I may solve this by removing the feature.

That’s without a doubt the easiest way to fix a bug!

Kurt, your first post should have referenced the fileinfo( function rather than the folderinfo statement/non-function. The former does indeed work on both files and folders and the fifth and sixth elements of the resulting array will give me the modification date and time.

Thank you and thanks to Gary for the useful advice on the UNIX timescript.

However, this just returns the information Apple has for the modification date and time. For a folder, I don’t think this is guaranteed to be correct in regards to the contents of the folder. In other words, one or more files inside the folder may have a newer modification date than the folder itself, even more so for nested folders.

I’ve never done that before, and I’m reluctant to do so now, but I am considering it.

Well, that takes me right back to where I started. I think I’ll stick with the brute force method - it doesn’t take long and I was just aiming for more elegant code, probably a pointless exercise these days.

Yes, I messed up the function I was recommending with your issue. But the code example was correct … :sweat_smile:

Please, don’t remove the statement!
I have modified the code in a procedure, and the procedure is working in my tests now. Hopefully you can use it to fix the copynewerfolder statement.

 fileglobal spath,dpath,sourcefiles,sourcefilenames,destfiles,destfilenames,slen,sfile,dfile
 choosefiledialog spath,"folders",true()
 choosefiledialog dpath,"folders",true()
 if spath match "*:" spath=trim(spath,1) endif
 if dpath match "*:" dpath=trim(dpath,1) endif
 statusmessage "filecatalog "+spath
 sourcefiles = filecatalog(spath)
 sourcefilenames = replace(sourcefiles,spath,"")
 statusmessage "filecatalog "+dpath
 destfiles = filecatalog(dpath)
 destfilenames = replace(destfiles,dpath,"")
 
 // tallmessage destfilenames STOP
 
 looparray sourcefilenames,cr(),sfile
     if fileexists(dpath+sfile)
         copynewerfile spath+sfile,dpath+sfile
         //message "Newer file copied."
         if error rtnerror info("error") endif
     else
         copyfile spath+sfile,dpath+sfile
         message "New file created."
         if error rtnerror info("error") endif
     endif
 endloop
 
 message "Files in the destination folder were synchronized with the source folder files."

P.S.: You can replace the fileglobal variables with local variables. I used the fileglobals here to check my variables in the Formula Workshop for debugging purposes.

I can simplify my code. There is no need to catalog the destination folder files. Additionally I noticed that the forum changed the asterisks to empty em spaces. So I changed the search formula from MATCH to ENDSWITH.

 local spath,dpath,sourcefiles,sourcefilenames,sfile
 choosefiledialog spath,“folders”,true()
 choosefiledialog dpath,“folders”,true()
 if spath endswith ":" spath=trim(spath,1) endif
 if dpath endswith ":" dpath=trim(dpath,1) endif
 statusmessage “filecatalog “+spath
 sourcefiles = filecatalog(spath)
 sourcefilenames = replace(sourcefiles,spath,””)
 looparray sourcefilenames,cr(),sfile
 if fileexists(dpath+sfile)
 copynewerfile spath+sfile,dpath+sfile
 if error rtnerror info(“error”) endif
 else
 copyfile spath+sfile,dpath+sfile
 if error rtnerror info(“error”) endif
 endif
 endloop
 
 message "Files in the destination folder were synchronized with the source folder files."

The forum uses asterisks for formatting. You can format your text as code by indenting every line by four spaces or more, or by placing 3 back tics on otherwise empty lines before and after your code. When you do that, nothing within the code is interpreted as formatting. It’s all displayed just the way you typed it. I used the second method to edit your code.

On a German keyboard, the back tic appears to be this key, with control and shift held down.
Screen Shot 2020-05-13 at 1.44.44 PM