Batching "SetAttr" leads to "file not found"

After testing my batch timeshift script (https://resource.dopus.com/t/dialog-button-for-batch-timeshifting-picture-metadata-with-syntax-check/38723/2) successfully im now running into problems in a production environment (batching ~2000 files). When starting the timeshift the SetAttr command is running into problems.

  • One is "metadata parsing error" but "batching" the single file works flawlessly.
  • The second is a "file not found". It seems that DOpus is renaming the file where SetAttr should be applied (a numeric is attached to the extension). Then the command fails with "system cannot find the file". As you can see in the image below the file which is not found is existent but with another extension.

    The command object im using is created once, the actual command added via AddLine() and via AddFiles() i add the selected files.
    My first approach was creating the command object and then applying it to each file individually. Thus i would be able to do better error catching but I changed it because it feeld slower.
    Can you give me an advise?

My guess is that you're applying multiple changes, one by one, to the files (e.g. click a button in the dialog to do one change, then click another to do a second change). That would mean you would need extra logic in your script to ensure all the changes have been seen by the file display, and the file list you're asking the Command object to act on is correct (not one with temporary file paths), between each set of commands that you run.

It's best to instead do all the changes at once with a single command. The SetAttr command can be given multiple timestamps to change at once, and specifying them all at once will let Opus take care of the details. It'll also be a lot faster in many cases, since it can do everything at once per file, instead of once per timestamp per file.

Well sorry my post was not precise enough. The one by one approach was my initial idea but i switched to this so all files are changed together

function ShiftTime(clickData, sourceDate, timeShift)
{
	var selectedFiles = clickData.func.sourcetab.selected_files;
	var cmd = DOpus.Create.Command;
	cmd.AddLine("SetAttr META \"" + sourceDate + ":" + timeShift + "\"");
    Log("SetAttr META \"" + sourceDate + ":" + timeShift + "\"");
	cmd.SetModifier("nodeselect");
	cmd.AddFiles(selectedFiles);
	cmd.Run();
}

The Log shows just one SetAttr so the command is executed just once, so there should be no multiple changes

Try this:

function ShiftTime(clickData, sourceDate, timeShift)
{
	var tab = clickData.func.sourcetab; // --- ADDED ---
	tab.Update(); // --- ADDED ---
	var selectedFiles = tab.selected_files; // --- CHANGED ---
	var cmd = DOpus.Create.Command;
	cmd.SetSourceTab(tab); // --- ADDED ---
	cmd.AddLine("SetAttr META \"" + sourceDate + ":" + timeShift + "\"");
    Log("SetAttr META \"" + sourceDate + ":" + timeShift + "\"");
	cmd.SetModifier("nodeselect");
	cmd.AddFiles(selectedFiles);
	cmd.Run();
}

Very nice and thanks alot! I was now able to batch edit ~1.5k without a problem. But in the first run the first file already failed because of another metadata parsing error which i was able to fix by just editing the first file.

But i struggle to see why your changes work. I visually see the differences and understand what they do one by one but not why they make the problems go away. Can you explain your thougts/the solution shortly to me?

And another question: im thinking about do deselect the files that were edited successfully (as some kind of safety because it can get annoying having inconsistent data in thousands of files). The approach would be to switch again to one by one editing (or maybe smaller batches), saving which files were selected (working on those information and not on tab.selected), editing and then deselecting those which were successfully edited. But this would be some effort and your advise was not doing so. Is there a simpler way?

Felix

"Metadata parsing error" seems to happen when the command's arguments aren't recognised. Maybe it can happen in other situations as well; I'm not actually sure without digging into things. e.g. If you ask it to increment a timestamp that doesn't exist on that file, it might fail with that error.

The file list at the time you take the selected_files snapshot must have still been processing changes from a previous run, where there was a temp file still in the list instead of the finished filename. Calling Update on the tab object forces it to get the tab's current view of the folder as a new snapshot. (That could still be out of date, if the tab hasn't processed all the changes yet, but it'd be unlikely unless you're clicking the button multiple times. You can avoid the problem entirely by having your script read the directory itself, but there's probably no need.)

That should happen automatically if you use the Command object given to you within the clickdata.func object. That is also set up with the correct source tab and list of selected files, so you can skip several lines of code by using that object. (I assumed there was a reason you weren't, since most of our examples use that object rather than create a new, empty Command object, but if not then try that out.)

Many Thanks for the explenation, got clearer to me now.

I thinkt that i at least found one case where that happens. If im using "datetaken" but in the selected files are videos (<> "recordingtime"). My guess is that the DOpus setattr dialog enumerates all files at first and caching the dates. At this process the error occurs. But then it says it fails at editing the first file. Sounds for me like a bug / imprecise error message. Should i file a bug report?

Well that case worked for me. I removed all information from the image with explorer properties dialog and ended up with a timestamp from 1601 :rofl:

Worked for me, didnt recognize. But i guess only when the command run completely successful (hadnt a case where it fails in the middle of the process since i used your improved version to test this kind of error). Honstley the reason why i didnt use it because i somehow get used to go with DOpus.Create.Command (was the only way i remembered). Thanks for stating out using the better way. :sunglasses:
Thanks for the help.