Rename files based on a json entry

Advanced Renamer forum
#1 : 05/04-20 21:21
Adri C-Fu
Adri C-Fu
Posts: 3
Good day, here's my situation.

I have a bunch of files in pairs.

0bed59e3284bac2503b5fb7e82fe2f5c.binary
0bed59e3284bac2503b5fb7e82fe2f5c.json

the json has a one-line entry:
{"id":"0bed59e3284bac2503b5fb7e82fe2f5c","name":"IMG-20191229-WA0049.jpg","size":177956,"filesize":"173.79 kB","type":"image/jpeg","lastModifiedDate":"2019-12-31T02:37:41.306Z","link":"http://lovingtzerica.my.to:2912/download/0bed59 e3284bac2503b5fb7e82fe2f5c/","path":"/opt/youtransfer/uploads/0bed59e3284bac2503b5fb7e82fe2f5c.binary","jsonPath":"/opt/youtransfer/uploads/0bed59e3284bac2503b5fb7e82fe2f5c.json","uploaded":1577759861309,"expires":1609382261309,"bundle":"bf3cb27a-6a1d-4d61-867f-7333f5006570"}

and I have a few hundred pairs of this.

so I'm searching for a way to rename the files based on the "name" value in the respective json files. Can AR do it?

Cheers and thanks!

Not sure if Advanced Renamer can get the value from


05/04-20 21:21
#2 : 06/04-20 00:59
David Lee
David Lee
Posts: 1125
Assuming that the format of the json file is always the same (ie the new file name is always 19 characters long, starting at character 50 in the json file, as in your example) then this script should do what you want:

sourceFile = item.filename.match(/(.*)(\..*$)/)[1] + '.json';
tag = '<File Content:49:19:"' + sourceFile + '">';
newName = app.parseTags(tag);
return newName;




06/04-20 00:59 - edited 06/04-20 01:07
#3 : 06/04-20 01:47
David Lee
David Lee
Posts: 1125
Reply to #2:

This script is better - file name lengths are not restricted.

sourceFile = item.filename.match(/(.*)(\..*$)/)[1] + '.json';
tag = '<File Content:0:99:"' + sourceFile + '">';
newName = app.parseTags(tag).match(/(name":")(.*)(\.)/)[2];
return newName;


06/04-20 01:47
#4 : 06/04-20 11:06
Adri C-Fu
Adri C-Fu
Posts: 3
Reply to #3:

Reply to #3:
Thank you for your reply, I appreciate it. But the script isn't working. I'll try to explain further the best that I can.

File #1: 0bed59e3284bac2503b5fb7e82fe2f5c.json
{"id":"0bed59e3284bac2503b5fb7e82fe2f5c","name":"IMG-20191229-WA0049.jpg","size":177956,"filesize":"173.79 kB","type":"image/jpeg","lastModifiedDate":"2019-12-31T02:37:41.306Z","link":"http://lovingtzerica.my.to:2912/download/0bed59 e3284bac2503b5fb7e82fe2f5c/","path":"/opt/youtransfer/uploads/0bed59e3284bac2503b5fb7e82fe2f5c.binary","jsonPath":"/opt/youtransfer/uploads/0bed59e3284bac2503b5fb7e82fe2f5c.json","uploaded":1577759861309,"expires":1609382261309,"bundle":"bf3cb27a-6a1d-4d61-867f-7333f5006570"}


File #2: 1c30a1f0e4b8cb852f28275b6cd33c61.json
{"id":"1c30a1f0e4b8cb852f28275b6cd33c61","name":"20191229_210005.jpg","size":2018531,"filesize":"1.93 MB","type":"image/jpeg","lastModifiedDate":"2020-01-02T13:39:36.729Z","link":"http://lovingtzerica.my.to:2912/download/1c30a1 f0e4b8cb852f28275b6cd33c61/","path":"/opt/youtransfer/uploads/1c30a1f0e4b8cb852f28275b6cd33c61.binary","jsonPath":"/opt/youtransfer/uploads/1c30a1f0e4b8cb852f28275b6cd33c61.json","uploaded":1577972376730,"expires":1609594776730,"bundle":"56f26b1a-8e8d-4038-892a-4cb32e7480e7"}


File #3: 94aa601b1ff250f2ad6e69abe8d29b27.json
{"id":"94aa601b1ff250f2ad6e69abe8d29b27","name":"ERICA TZE SING Prewedd.mp4","size":143333980,"filesize":"136.69 MB","type":"video/mp4","lastModifiedDate":"2019-12-30T14:33:32.207Z","link":"http://lovingtzeerica.my.to:2912/download/94aa6 01b1ff250f2ad6e69abe8d29b27/","path":"/opt/youtransfer/uploads/94aa601b1ff250f2ad6e69abe8d29b27.binary","jsonPath":"/opt/youtransfer/uploads/94aa601b1ff250f2ad6e69abe8d29b27.json","uploaded":1577716412210,"expires":1609338812210,"bundle":"4ebf3142-4899-42ca-885d-c969d60174d7"}


What i notice in the json files:
1. The id has the same length (32 characters)
2. The name includes extension, and can have spaces in between (eg. ERICA TZE SING Prewedd.mp4
3. "name":xxxxxx always starts at column (position) 42, if you count from 1 from the left.
4. the value for "name" can have any length that possible filenames can have in windows
5. I'm just guessing, but I think the it's easier if filename+ext starts from the 7th occurrence of the character " (or from POS 50) to the 8th occurrence of the character "
6. 2nd script returns an error:
<>:/\*? is not supported in filenames
for some pairs, For others it partially works - the extension are still .json and .binary.


as for #5 I'm not sure if it's possible to find occurrence numbers, but while the scripts doesn't work, it looks awesome. Never knew something like this is possible!

Thanks again!


06/04-20 11:06 - edited 06/04-20 11:19
#5 : 06/04-20 14:21
David Lee
David Lee
Posts: 1125
Reply to #4:
It seems that I misunderstood what you were trying to do. I assumed that you wanted to rename ALL your files to the filename coded in the json file.

Now it appears that it is only the .binary files you wish to rename - including the extension.

Try this script but only load the .binary files into the list:

sourceFile = item.filename.match(/(.*)(\..*$)/)[1] + '.json';
tag = '<File Content:0:305:"' + sourceFile + '">';
newName = app.parseTags(tag).match(/(name":")(.*?)(")/)[2];
return newName;

I've increased the number of characters read from the .json file to 305, which will allow for the maximum size of a Windows filename. However this number must be less than the total number of characters in the shortest .json file otherwise the script will fail. You need to read enough characters from the file to include the new filename without trying to read past the end of the file, so you may need to tweak this parameter if you have problems.

There is another, undocumented, tag - <File Line> - which is supposed to "work like the <File Content> tag but read whole lines from the file, which is exactly what we want to do. Unfortunately this tag doesn't appear to have an optional FILENAME argument, so it will only work on the file you want to rename (ie .binary) and you can't use it to extract the filename from the corresponding .json file.

Another approach would have been to rename the .binary files and then use the "Pair renaming feature" to copy the names to the .json files. Unfortunately ARen always selects the .binary files as the pairs, which is the wrong way round.


06/04-20 14:21 - edited 06/04-20 14:27
#6 : 06/04-20 15:15
Adri C-Fu
Adri C-Fu
Posts: 3
Reply to #5:
Many thanks for your time.... it works! Apologies for not explaining more for what I wanted to do.

Just a bit of a background, a friend wanted a way for his wedding guests to upload his wedding photos and videos, so I just created a quick youtransfer docker container for him. Didn't know that youtransfer renamed the files after uploading.

Thank you again. I'd like to understand more on these things:
(/(.*)(\..*$)/)
(.*?)(")/

how/where would I start?

Cheers!


06/04-20 15:15
#7 : 06/04-20 16:58
David Lee
David Lee
Posts: 1125
Reply to #6:
I'm glad it finally worked!

Those obscure looking strings are "Regular Expressions", used for pattern searching in text. They take a bit of getting used to but are quite simple when you get the hang of them.

A good place to start is the Advanced Renamer Getting Started Guide: www.advancedrenamer.com/user_guide/regular_expresions.

For further help you will need to search the Internet - and there is a good intro on Wikipedia. It helps to understand that ARen uses a particular dialect: - PCRE (Perl Compatible Regular -Expressions) and not all currently available PCRE features are implemented.

See if you can get to grips with regex in normal renaming methods first - the implementation is a bit more complicated in JavaScript.

To get you started I'll try to explain the regex: "(name":")(.*?)(")"

First of all consider it without the parentheses: ie: name":".*?"

This is searching the original string for the literal text name":" followed by any number of characters, then a quotation mark - ie the substring - name":"<filename.ext>". If a match is possible then the regex will return this string otherwise null.

In a regex a full stop on its own represents any single character (if you actually wanted to match a full stop then you would have to prefix it with the Escape character ie "\.").

The star character is a multiplier and means the previous character must be matched any number of times (including zero) so in this case .*" will match as many characters as possible up to and including a quotation mark.

However, by default "*" will keep going as long as possible and match characters up to the last quotation mark in the string - behaviour usually described as greedy. This is why you encountered the "unsupported character" error in my original script - the match continued to gobble up characters following the end of the filename, including "illegal" characters.

Adding a question mark - *? - will tame the multiplier and make it "lazy", so that the match will stop at the first instance of the following character. (Note that this feature isn't documented in Kim's introduction in the User Guide).

The parentheses in "(name":")(.*?)(")" split the match up into three sub-expressions. The regex is still looking for the same match overall but now it returns the result of the match in three separate strings.

In an ordinary renaming method these are returned in the variables \1, \2 and \3 so, if the match is successful:
\1 = name":"
\2 = <filename.ext>
\3 = "
and you would just use \2 for the new filename.

The implementation is a bit different in a script:
string.match(/(name":")(.*?)(")/)[2]

Here "match" is a JavaScript method that searches the variable "string" for the pattern supplied in the argument and placing the pattern between a pair of forward slashes now indicates that it is a regular expression.

In JavaScript, a regex with sub-expressions returns a string array in which element zero returns the complete match and the individual sub-matches are returned in subsequent array elements. In this case the filename is returned in element [2].

It's probably more obvious if the code is expanded thus:

tag = '<File Content:0:305:jsonFilePath>';
string = app.parseTags(tag);
resultArray = string.match(/(name":")(.*?)(")/);
newFileName = resultArray[2];
return newFileName;

I hope that hasn't caused you even more confusion!






06/04-20 16:58 - edited 06/04-20 17:00