help with javascript needed - convert double backslashes

Started by Carlo Didier, November 07, 2024, 09:06:43 PM

Previous topic - Next topic

Carlo Didier

I'm blowing my head off with javascript again ...
I need to pass a full image path to an external program (exiftool, to extract the preview jpg from DNG files).
Unfortunately, the string returned from iMatch has all backslashes doubled, so I need to normalize that to single backslashes. I tried several things and this should work, but it has no effect:
[color=#cccccc][size=3][font=Consolas, Courier New, monospace][color=#9cdcfe]item[/color][color=#d4d4d4].[/color][color=#9cdcfe]fileName[/color][color=#d4d4d4].[/color][color=#dcdcaa]replace[/color][color=#d4d4d4]([/color][color=#d16969]/[/color][color=#d7ba7d]\\[/color][color=#d16969]/[/color][color=#569cd6]g[/color][color=#d4d4d4], [/color][color=#ce9178]'[/color][color=#d7ba7d]\\[/color][color=#ce9178]'[/color][color=#d4d4d4])[/color][/font][/size][/color]

 
The replacement string '\\' should result in a single backslash, but is seems to have no effect. Here is the output of the original item and the string which should have been changed, but isn't:
[
  {
    "folder": "\\\\LochEwe\\Photography\\Photos Carlo\\2009\\05\\2009-05-24 Flowers\\",
    "name": "D20090524001.dng",
    "namene": "D20090524001",
    "ext": ".dng",
    "fileName": "\\\\LochEwe\\Photography\\Photos Carlo\\2009\\05\\2009-05-24 Flowers\\D20090524001.dng"
  }
]
"\\\\LochEwe\\Photography\\Photos Carlo\\2009\\05\\2009-05-24 Flowers\\"

Javascript always drives me nuts. And don't get me ranting over the inconsistencies between IMWS and javascript (like having to ask for the field "filename" to effectively get another field named "fileName" ... total nonsense)

Mario

JSON requires all strings to have \ escaped as two \\.
This is why responses from IMatch look that way. But JavaScript automatically resolves \\ to \ when you access the JSON.

So, response.files
  • .fileName
  • will return "\\LochEwe\Photography\Photos Carlo\2009\05\2009-05-24 Flowers\D20090524001.dng" automatically. No manual replacements needed.

You did not provide any source code. At least what you copied and pasted into the code tag is unreadable.
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

Carlo Didier

Uh, sorry, that paste for the code went wrong (when you do several things at the same time and don't know anymore what's in the clipboard ...).
Here's my code:
console.log(JSON.stringify("--- started ---",null,2));
strExtractTool = "C:\\Program Files\\photools.com\\imatch6\\exiftool.exe";
console.log(JSON.stringify(strExtractTool,null,2));
IMatch.get('v1/files',{
idlist: IMatch.idlist.fileWindowSelection,
fields: 'folder,name,namene,ext,filename'
}).then(function(response) {
arrFiles = response.files;
console.log(JSON.stringify(arrFiles,null,2));
console.log(JSON.stringify(arrFiles[0].folder,null,2));
// IMatch.get('v1/folders/create',{
//     parentpath: arrFiles[0].folder,
//     foldername: 'JPG'
// }).then(function(response) {
// console.log(JSON.stringify(response,null,2));
arrFiles.forEach(item => {
strParameters = '-b -JpgFromRaw \"' + item.fileName + '\" > \"' + item.folder + 'JPG\\' + item.namene + '.jpg\"';
console.log(JSON.stringify(strParameters,null,2));
IMatch.shellExecute({
'executable' : '\"' + strExtractTool + '\"',
'parameters' : strParameters,
'showwindow' : true
});
});
});
console.log(JSON.stringify("--- done ---",null,2));
IMatch.modalClose();

Mario

You are using the old-style .then(... syntax.
It will become much simpler when you use the standard async/await.

I've created a function with the attribute async named processFiles() and call it from my code.

async function processFiles()
{
    const response = await IMWS.get('v1/files',{
        idlist: IMatch.idlist.fileWindowSelection,
        fields: 'folder,name,namene,ext,filename'
    });

    response.files.forEach((f) => {
        console.log(f.fileName);
    })
}

and then elsewhere I call it:

processFiles();

The processFile() function fetches the same info your code does, and uses console.log to output the fileName.
The output looks like this:

E:\data\AI_DATASETS\AI_TEST\birds\gulls-370012_1280.jpg
E:\data\AI_DATASETS\AI_TEST\birds\swan-2350668_1280.jpg
E:\data\AI_DATASETS\AI_TEST\birds\swan-2077219_1280.jpg

No \\ anywhere!

You use JSON.stringify in your code to output info to the console. But JSON.stringify takes an object and converts it back into JSON text, replacing \ with \\ in strings during this process. This is what makes you think the fileName has double \\.

Where I call console.log(fileName) you would do your IMatch.shellExecute[).

NOTE: shellExecute does not wait for the external process to finish. If you run your script with 100 files selected, you will launch 100 ExifTool instances!

NOTE: You can run ExifTool commands on all files in a folder, using the correct syntax. May be easier than running it on each individual file?

-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

Carlo Didier

Thanks for the clarifications. It's a first try at this script. If I loose too much time with javascript, I'll switch back to Powershell and have the iMatch app just call that.

As for the number of files, I thought of having two options: Either select a number of files or a folder. In the first case, only selected files would be treated, in the second, all files in the selected folder.

And I would largely prefer to run exiftool seperately and sequencially for each file. Imagine a larger number of files with long paths (these might be selected from a category which may contain files with varioud paths). I'm pretty sure that at some point you won't be able to pass that super long list as a parameter anymore. In any case, you would have to add checks to ensure it doesn't get too long and then split it up anyway. All unnecessary complications. Keep it simple (by just processing each file one after another).

Mario

You can write an .arg text file (IMatch uses arg files e.g. in the ExifTool Command Processor).

No limits on the number of files etc., ExifTool launches once and processes all arguments and file names in the arg file.
Depending on your needs you write one set of arguments with a file name for each file you want ExifTool to process.

Built the arg file contents in memory from your parameters and file names. Each parameter on a separate line (delimit each row with \r\n)

-b
-JpegFromRaw
...
<source file name>
<output file name>
-execute

-b
-JpegFromRaw
...
<source file name>
<output file name>
-execute

Add an -execute after each set to tell ET to run now.

When done, call IMatch.writeTextFile to save the arguments to a file on disk and then call shellExecute once with "exiftool.exe -@ <name of args file".

Most flexible way to do this.
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook