According to the manual, LrFileUtils.fileAttributes ( path ) "retrieves the file attributes for the file or directory at a given path." So I'm trying:
folderPath = string.gsub( photo.path, photo:getFormattedMetadata('fileName'), '')
phoAttributes = LrFileUtils.fileAttributes( folderPath)
folderSize = phoAttributes['fileSize']
First of all I'd try using LrPathUtils.parent( photo.path ) to set folderPath.That might help if the folder naming is the problem as you suspect.
I'm surprised that fileAttributes would allow you to read the size of a folder, regardless of what the documentation says. At the OS level one is an atomic transaction and the other involves iterating through all the contents of the directory and checking their MFT entries (etc). My guess is this is a documentation bug. When I've determined folder size I've iterated through all files directly or recursively in the folder and checked the fileAttributes for each file depending upon what I need at the time. Even if it does work you may choose not to use it at times because it will either return direct or recursive folder size, and you may need the other size.
Just looked at the results of LrFileUtils.fileAttributes on my Mac and the value it returned for fileSize goes in the category of "pedantically correct, but not at all useful." The fileSize for the directory on my Mac containing the entire source tree for Lightroom was 646 bytes (!). There's umm ... just a little bit more source code than that in there.
What I believe this means is the "file" that the Mac file system uses to represent that top-level directory is itself 646 bytes long (presumably containing names, attributes, pointers, etc. of the files and folders that are immediate children of that folder), but obviously not measuring the contents.
On the Mac, you might be able to shoehorn the du command into giving you the info you're seeking, if you don't need exact byte counts. (I think the best it can give is 1K block counts.) Perhaps someone can chime in with a similar answer for Windows.
Thanks both. LrPathUtils was a more direct way of getting what was still the wrong data, as Eric found. As the plug in loops through the target photos, I think I'll just build an array based on the folder paths and pass the images' size to it. Though it'll overlook uncatalogued files in the folders, it should be sufficient for the use I have in mind.
On the Mac, you might be able to shoehorn the du command into giving
you the info you're seeking, if you don't need exact byte counts. (I
think the best it can give is 1K block counts.) Perhaps someone can
chime in with a similar answer for Windows.
If you are going to be calling a command line app to work out directory size you might as well write a little extra code in LR to count up the size yourself. A LrFileUtils.recursiveFiles loop and LrFileUtils.fileAttributes.fileSize will do the trick. There will be a cut off point where it will be more efficient to hand the task off to the OS commands, but your plugin's purpose might mean this is not going to be an issue, or you might be able to kick this off as an async task early enough that the users won't notice the time being taken.
Re the Windows question, you can find du commands you could distribute with the plugin. Or use dir /s /-c and only pay attention to the second last line of the response.
If you are going to be calling a command line app to work out directory size you might as well write a little extra code in LR to count up the size yourself. A LrFileUtils.recursiveFiles loop and LrFileUtils.fileAttributes.fileSize will do the trick. There will be a cut off point where it will be more efficient to hand the task off to the OS commands, but your plugin's purpose might mean this is not going to be an issue, or you might be able to kick this off as an async task early enough that the users won't notice the time being taken
I'd encourage you to do some performance testing before committing to this approach. I suspect a small command-line app that's written specifically for this purpose would outperform Lightroom, especially for large directories (i.e. thousands or millions of files).
John - If it were me, my approach on Windows would be to use cscript.exe which comes standard on every copy of Windows since XP. It's a command-line utility that executes VBScript (search online for Windows Script Host) and comes with object interfaces that expose file system functionality, etc. This way I wouldn't have to supply a non-standard executable as part of my plug in. The order of events would be:
- generate a temp file containing the VBScript code.
- execute the code: "cscript.exe mytempfile.vbs > myoutput.txt"
- read the contents of myoutput.txt into the variable for the directory size
- delete myoutput.txt
This is tedious but each individual step is not too hard. For instance, the VBScript code is a few lines:
dim fs, folder
set fs = WScript.CreateObject("Scripting.FileSystemObject")
set folder = fs.GetFolder("YourPathNameHere")
With a couple more lines of VBScript code, you can pass in the path name as an argument so you don't have to do "code generation" at run-time.
I think you and I have previously traded ideas on a wrapper function that executes an app and gathers its output into a variable. That would be handy here.
Thanks Dave. I'm much more at home on Windows and was wondering if I'd have to go via WSH and VB - the Mac side of it is much less familiar (would have though "du" was a Canadian pronuniciation of "doh"). I guess I've got to decide if I want to return the size of the actual directories, or analyse the target photos by directory. If anything I'm leaning towards the latter, in which case I either battle on building arrays or write and read back some XML . At some point though, I suspect one of us is going to have to give this temporary file approach a go.
If I can find the time, I may take a stab at it this weekend. Sounds like a fun little self-contained project.