You are not logged in.
Unfortunately, RegEx engine that is used in ReNamer doesn't support that kind of tags in replace part of regex (although they exist, and it is possible to do such a job with regexes if they are fully implemented; but unfortunately - not in ReNamer)...
But you can do that with PascalScript using eg. regex functions of PascalScript, especially:
function SubMatchesRegEx(const Input, Find: WideString; const CaseSensitive: Boolean): TStringsArray;
which for given filename (Input) will create an array of matching groups for a given regex (Find).
So if you get your example as an Input:
David Guetta Feat. Chris Willis - Love Is Gone (Original Mix).mp3
and regex: "\w+\s(\w+) Feat. \w+\s(\w+) - .+"
it should create an array of two strings: Guetta and Willis (groups are strings that are matched by regex inside brackets).
Then you can use
function WideUpperCase(const S: WideString): WideString;
on these strings and glue it back together for nice filename.
Let me know if you succeded. Otherwise I write it for you.
For more info about regex functions in PascalScript take a look at
http://www.den4b.com/forum/viewtopic.php?id=433
Cheers,
Konrad
Last edited by krtek (2008-08-17 00:46)
Regular Expressions are not as hard to understand as you may think. Check ReNamer's manual or nice Regular Expressions tutorial for more info and start to use full power of applications that use them (like ReNamer, Mp3Tag and so on).
Offline
Unfortunately, RegEx engine that is used in ReNamer doesn't support that kind of tags in replace part of regex (although they exist, and it is possible to do such a job with regexes if they are fully implemented; but unfortunately - not in ReNamer)...
If they exist like you said, I hope that Denis will implement these tags, if is possible of course
I read the posts at ReplaceRegEx and MatchesRegEx functions in PascalScript, but I cannot figure out where to put function SubMatchesRegEx(const Input, Find: WideString; const CaseSensitive: Boolean): TStringsArray;
As I said before I'm not experienced with Pascal, so could you make a script?
Make those parts in code bold to emphasize future possible edits, too; I hope that script which you'll write is universal for any case changings, in every possible word in filename, only you should specify the lenght (pattern) of filename using RegEx, in this case "\w+\s(\w+) Feat. \w+\s(\w+) - .+", and then do WideUpperCase or other function for case change you need for, right?
Last edited by eR@SeR (2008-08-17 02:30)
TRUTH, FREEDOM, JUSTICE and FATHERLAND are the highest morale values which human is born, lives and dies for!
Offline
If they exist like you said, I hope that Denis will implement these tags, if is possible of course
It's out of Dennis power, because he uses third party regex engine.
More info in: http://www.den4b.com/forum/viewtopic.php?id=428
I'll write the script when I find some spare time. I'm moving from UK back to Poland tomorrow, so it might take some time.
Last edited by krtek (2008-08-17 11:03)
Regular Expressions are not as hard to understand as you may think. Check ReNamer's manual or nice Regular Expressions tutorial for more info and start to use full power of applications that use them (like ReNamer, Mp3Tag and so on).
Offline
I'll write the script when I find some spare time...
No need for rush... Relax and rest in Poland and have a nice trip (maybe this wish is overdue)
Thanks anyway for making things clear...
Cheers
TRUTH, FREEDOM, JUSTICE and FATHERLAND are the highest morale values which human is born, lives and dies for!
Offline
The DAY has come
Sorry for lating so #%@!# long, eR@SeR.
But it works!
const
REGEX = '.+\s(\w+) Feat. \w+\s(\w+) - .+|.+\s(\w+)\s-\s.+';
REGEX2 = '.+\s(\w+)\s-\s.+'; //you won't need these two (it's just the one above splitted in halves)
REGEX3 = '.+\s(\w+) Feat. \w+\s(\w+) - .+';
CASE_SENSITIVE = False;
var
Matches, SubPatterns : TStringsArray;
TempFilename : WideString;
start_pos, end_pos, i : Integer;
Initialized : Boolean;
begin
TempFilename:='';
end_pos:=0;
start_pos:=1;
SetLength(SubPatterns,0);
SetLength(Matches,0);
Matches:=MatchesRegEx(Filename, REGEX, CASE_SENSITIVE);
if Length(Matches) <= 0 then exit;
if Matches[0] <> Filename then
if DialogYesNo('RegEx didn''t match the full filename.' +#10+ 'Would you like to continue?')=false then exit;
SubPatterns:=SubMatchesRegEx(Matches[0],REGEX,CASE_SENSITIVE);
if Length(SubPatterns) <=0 then exit;
for i:=0 to Length(SubPatterns)-1 do
if SubPatterns[i]<>'' then
begin
end_pos:=WidePos(SubPatterns[i], Matches[0])-1;
TempFileName:=TempFileName+WideCopy(Matches[0], start_pos, end_pos-start_pos+1);
start_pos:=end_pos+Length(SubPatterns[i])+1;
TempFilename:=TempFileName+WideUpperCase(SubPatterns[i]);
end;
if start_pos < Length(Matches[0]) then
TempFilename:=TempFileName+WideCopy(Matches[0], start_pos, Length(Matches[0])-start_pos+1);
FileName:=TempFileName;
end.
Last edited by krtek (2009-02-15 23:16)
Regular Expressions are not as hard to understand as you may think. Check ReNamer's manual or nice Regular Expressions tutorial for more info and start to use full power of applications that use them (like ReNamer, Mp3Tag and so on).
Offline
Doesn't matter, important thing is that you gave respond and thanks for that
It works for following examples as I asked:
David GUETTA Feat. Chris WILLIS - Love Is Gone (Original Mix).mp3
and
Eddy WATA - I Love My People.mp3
Geo Da SILVA - Feelin' So Good (Long Mix).mp3
I noticed this...if you want to use And, &, Featuring, Ft. instead Feat. you can edit code in first REGEX (second line of code), type one of it and you'll get the same output. Excellent
Sorry for "making your life harder"...could you help with these ones?
Jean-Michel Jarre --> Jean-Michel JARRE
Predrag Stojakovic --> Predrag STOJAKOVIC
Geo Da Silva --> Geo Da SILVA
Tip: code will make last word UPPER no matter what's in front of it (if possible).
Note: It will be used for names and surnames.
Important (!) question:
Your code makes ALL UPPER CASE in these examples...so is there a line in code that we can change/edit to do all lower case or First letter capital manipulation or you should create new one for that?
Refering to your new code too (second example)!
P.S. IMO your feedback here can give enough answers/solutions for these situations so go ahead BUT you don't have to hurry
TRUTH, FREEDOM, JUSTICE and FATHERLAND are the highest morale values which human is born, lives and dies for!
Offline
Just a quick reply:
There is a line in the code:
TempFilename:=TempFileName+WideUpperCase(SubPatterns[i]);
If you change that function for WideLowerCase you'll get all lowercase. First letter capital would need something like that:
TempFilename:=TempFileName+WideUpperCase(SubPatterns[i][1])+WideLowerCase(WideCopy(SubPatterns[i], 2, Length(SubPatterns[i])-1));
I will play a bit more with that script, to make these things easier...
Tip: code will make last word UPPER no matter what's in front of it (if possible).
Note: It will be used for names and surnames.
And what about things that are AFTER that surname, eg. song title?
If there is nothing after then this regex should be enough:
'.+\s(\w+)$'
Hmmm... But we need to match for the filename without extention... Ok, quick patch.
const
REGEX = '.+\s(\w+)$';
REGEX2 = '.+\s(\w+) Feat. \w+\s(\w+) - .+|.+\s(\w+)\s-\s.+'; //just a backup of the old regex
CASE_SENSITIVE = False;
var
Matches, SubPatterns : TStringsArray;
TempFilename, FileNameNoEXT : WideString;
start_pos, end_pos, i : Integer;
Initialized : Boolean;
begin
TempFilename:='';
end_pos:=0;
start_pos:=1;
SetLength(SubPatterns,0);
SetLength(Matches,0);
FileNameNoEXT:=WideStripExtension(FileName);
Matches:=MatchesRegEx(FileNameNoEXT, REGEX, CASE_SENSITIVE);
if Length(Matches) <= 0 then exit;
if Matches[0] <> FileNameNoEXT then
if DialogYesNo('RegEx didn''t match the full filename.' +#10+ 'Would you like to continue?')=false then exit;
SubPatterns:=SubMatchesRegEx(Matches[0],REGEX,CASE_SENSITIVE);
if Length(SubPatterns) <=0 then exit;
for i:=0 to Length(SubPatterns)-1 do
if SubPatterns[i]<>'' then
begin
end_pos:=WidePos(SubPatterns[i], Matches[0])-1;
TempFileName:=TempFileName+WideCopy(Matches[0], start_pos, end_pos-start_pos+1);
start_pos:=end_pos+Length(SubPatterns[i])+1;
TempFilename:=TempFileName+WideUpperCase(SubPatterns[i]);
end;
if start_pos < Length(Matches[0]) then
TempFilename:=TempFileName+WideCopy(Matches[0], start_pos, Length(Matches[0])-start_pos+1);
FileName:=TempFileName+WideExtractFileExt(FileName);
end.
It works for both examples. You just need to change regex at the beginning.
Tell me how it works.
Edited 16.02.2009 19:00
Few words of comment, how it works. The script changes case of every backrefference match (so it will alter case of every part of the whole match that is in parenthesis () in regex).
If you know that, you can use regex like that:
'.+\s(\w+)\s(Feat\.|ft\.|&|And|Featuring)\s\w+\s(\w+) - .+|.+\s(\w+)\s-\s.+'
and make all the Feat., ft., & and anything else in one go (just remember to escape dots "\.").
The only drawback is that all these words will have the case changed by the script (because they must to be appear in parenthesis; otherwise the alternation would be widened for whole expression).
But I guess it might be easier to do it in one go, and then simply replace these few words with same words in correct case, eg. FEAT->Feat, FT->ft and so on...
Last edited by krtek (2009-02-22 17:04)
Regular Expressions are not as hard to understand as you may think. Check ReNamer's manual or nice Regular Expressions tutorial for more info and start to use full power of applications that use them (like ReNamer, Mp3Tag and so on).
Offline
I've got something special.
Renewed script with:
1. Basic error handling (it will ask what to do if regex won't match full FileName)
2. Skipping of given words (so you can do your job in one go: just write good regex and tell the script which words to omit)
3. All controls at the beginning (set CHANGE_CASE to 1 for Uppercase, 2 for Lowercase, 3 for First letter capital)
I hope it was worth so long waiting.
With that regex it will react for words Feat., ft., &, And, Featuring... But you can add more.
const
//SCRIPT CONTROLS:
//Legend:
//1. Uppercase
//2. Lowercase
//3. First letter capital
CHANGE_CASE = 1;
REGEX = '.+\s(\w+)\s(Feat\.|ft\.|&|And|Featuring)\s\w+\s(\w+) - .+|.+\s(\w+)\s-\s.+';
//Backup REGEX's
//'.+\s(\w+) Feat. \w+\s(\w+) - .+|.+\s(\w+)\s-\s.+';
//'.+\s(\w+)$';
TO_SKIP = 'Feat.|ft.|&|And|Featuring'; //Here you can put words that you want to be skipped by script.
//The case convertion won't be applied to them.
//Seperate them with DELIMITER
//And remember that you need to make them explicit. Remove any escape signs.
//They need to be strings already matched by regex, so Feat. instead of Feat\.
DELIMITER = '|'; //Delimiter of words in TO_SKIP string
CASE_SENSITIVE = False; //Should searching with regex be case sensitive? Default: False
//END OF SCRIPT CONTROLS
var
Matches, SubPatterns : TStringsArray;
TempFilename, FileNameNoEXT : WideString;
start_pos, end_pos, i, j : Integer;
Initialized, TimeToExit, NeedSkipping, NotAFullMatch : Boolean;
Skip : TStringsArray;
Answer : WideString;
procedure Initialize;
begin
Skip:=WideSplitString(TO_SKIP, DELIMITER);
Answer:='Type just word BREAK in here to exit the script';
end;
begin
if not TimeToExit then
begin
if not Initialized then Initialize;
TempFilename:='';
end_pos:=0;
start_pos:=1;
SetLength(SubPatterns,0);
SetLength(Matches,0);
NotAFullMatch:=false;
FileNameNoEXT:=WideStripExtension(FileName);
Matches:=MatchesRegEx(FileNameNoEXT, REGEX, CASE_SENSITIVE);
if Length(Matches) <= 0 then exit;
if Matches[0] <> FileNameNoEXT then NotAFullMatch:=true;
SubPatterns:=SubMatchesRegEx(Matches[0],REGEX,CASE_SENSITIVE);
if Length(SubPatterns) <=0 then exit;
for i:=0 to Length(SubPatterns)-1 do
if SubPatterns[i]<>'' then
begin
NeedSkipping:=false;
end_pos:=WidePos(SubPatterns[i], Matches[0])-1;
TempFileName:=TempFileName+WideCopy(Matches[0], start_pos, end_pos-start_pos+1);
start_pos:=end_pos+Length(SubPatterns[i])+1;
for j:=0 to Length(Skip)-1 do
if WideSameText(SubPatterns[i],Skip[j]) then NeedSkipping:=true;
if not NeedSkipping then
case CHANGE_CASE of
1 : TempFilename:=TempFileName+WideUpperCase(SubPatterns[i]);
2 : TempFilename:=TempFileName+WideLowerCase(SubPatterns[i]);
3 : TempFilename:=TempFileName+WideUpperCase(SubPatterns[i][1])+WideLowerCase(WideCopy(SubPatterns[i], 2, Length(SubPatterns[i])-1));
else
begin
ShowMessage('The value of CHANGE_CASE constant is invalid. Check legend for info.');
TimeToExit:=True;
break;
end;
end
else
TempFilename:=TempFileName+SubPatterns[i];
end;
if start_pos < Length(FileNameNoEXT) then
TempFilename:=TempFileName+WideCopy(FileNameNoEXT, start_pos, Length(FileNameNoEXT)-start_pos+1);
if NotAFullMatch then
if not WideInputQuery('RegEx didn''t match the full filename.', 'Old filename:'+#10+FileName+#10+#10+'Proposed new filename: '+#10+TempFileName+WideExtractFileExt(FileName)+#10+#10+'What should we do?'#10+#10+'Pressing OK button = Rename that file'+#10+'Pressing Cancek button = Skip that file'+#10+'Type ''break'' in the text field to exit the script'+#10, Answer) then
exit
else if WideSameText(WideLowerCase(Answer),'break') then
begin
TimeToExit:=True;
exit;
end
else
Answer:='Type just word BREAK in here to exit the script';
FileName:=TempFileName+WideExtractFileExt(FileName);
end
else exit;
end.
Cheers,
Konrad
Last edited by krtek (2009-02-17 06:56)
Regular Expressions are not as hard to understand as you may think. Check ReNamer's manual or nice Regular Expressions tutorial for more info and start to use full power of applications that use them (like ReNamer, Mp3Tag and so on).
Offline
Sorry for long reply I was busy lately...
WOW, your last code is brilliant
It does almost 'anything'. Like you said:
(so you can do your job in one go: just write good regex and tell the script which words to omit)
I hope it was worth so long waiting.
YES!
Nothing more to add...
Cheers
TRUTH, FREEDOM, JUSTICE and FATHERLAND are the highest morale values which human is born, lives and dies for!
Offline
Hi again,
I needed to upgrade the script a bit, so I post it here for you guys as well.
Now you can choose the different case for EVERY capturing group.
And you can skip extention if you want.
ATTENTION: I've changed the meaning of digits for case functions to match the order in ReNamer's Case Rule.
I've also added iNVERT cASE and No changes possibility. The last one made TO_SKIP string obsolete so script works quicker now.
I guess it would be nice to add FORCE CASE FOR FRAGMENTS as well.
But I don't think I would be able to do this in an elegant way.
Dennis, maybe you could share your function for that part of Case Rule? Of course if it is "scriptable" (possible to transfer into the scipt ).
For now you can use Force Case For Fragments from Case Rule (with "none of the above") just after that script.
const
//SCRIPT CONTROLS:
REGEX = '(.+) - (.+) - (.+)';
CHANGE_CASE = '103';
SKIP_EXTENTION = true; //true or false
CASE_SENSITIVE = False; //Should searching with regex be case sensitive? Default: False
FULL_MATCH_CHECK = True; //Should the script warn you if regex didn't match the full filename? Default: True;
//Legend for CHANGE_CASE parameter:
//1. Capitalize Every Word
//2. lowercase
//3. UPPERCASE
//4. iNVERT cASE
//5. First letter capital
//0. No changes
//You may specify case for every capturing group (brackets) in regex as a string of appropriate digits.
//If the CHANGE_CASE string is shorten then number of capturing groups then the last digit is used till the end of regex.
//If the CHANGE_CASE string is longer, spare digits are ignored.
//eg. '102' means that first matched brackets will be uppercased, second - won't be changed and third (and every brackets after it) - lowercased.
//END OF SCRIPT CONTROLS
BREAK_STRING = 'BREAK';
FOR_ALL_STRING = 'DO NOT ASK';
STANDARD_ANSWER = BREAK_STRING+' to exit, '+FOR_ALL_STRING+' to continue';
var
Matches, SubPatterns : TStringsArray;
TempFilename, FileNameProcessedPart : WideString;
start_pos, end_pos, i, j : Integer;
Initialized, TimeToExit, NotAFullMatch, CheckIfFullMatch : Boolean;
CaseFlags : array of Integer;
CaseFlag : Integer;
Answer : WideString;
function SetCaseFlags(s : WideString) : array of Integer;
var
i : Integer;
LoopEnd : Integer;
CaseIDs : array of Integer;
begin
SetLength(CaseIDs,Length(s));
LoopEnd:=Length(s)-1;
for i:=0 to LoopEnd do
begin
CaseIDs[i]:= StrToInt(WideCopy(s,1,1));
s:=WideCopy(s,2,Length(s)-1);
end;
result:= CaseIDs;
end;
procedure Initialize;
begin
Answer:=STANDARD_ANSWER;
CheckIfFullMatch:=FULL_MATCH_CHECK;
Initialized:=true;
CaseFlags:=SetCaseFlags(CHANGE_CASE);
end;
begin
if not TimeToExit then
begin
if not Initialized then Initialize;
TempFilename:='';
end_pos:=0;
start_pos:=1;
SetLength(SubPatterns,0);
SetLength(Matches,0);
NotAFullMatch:=false;
if SKIP_EXTENTION then
FileNameProcessedPart:=WideStripExtension(FileName)
else
FileNameProcessedPart:=FileName;
Matches:=MatchesRegEx(FileNameProcessedPart, REGEX, CASE_SENSITIVE);
if Length(Matches) <= 0 then exit;
if Matches[0] <> FileNameProcessedPart then NotAFullMatch:=true;
SubPatterns:=SubMatchesRegEx(Matches[0],REGEX,CASE_SENSITIVE);
if Length(SubPatterns) <=0 then exit;
for i:=0 to Length(SubPatterns)-1 do
if SubPatterns[i]<>'' then
begin
end_pos:=WidePos(SubPatterns[i], Matches[0])-1;
TempFileName:=TempFileName+WideCopy(Matches[0], start_pos, end_pos-start_pos+1);
start_pos:=end_pos+Length(SubPatterns[i])+1;
if i < length(CaseFlags) then
CaseFlag:=CaseFlags[i]
else
CaseFlag:=CaseFlags[Length(CaseFlags)-1];
case CaseFlag of
0 : TempFilename:=TempFileName+SubPatterns[i];
1 : TempFilename:=TempFileName+WideCaseCapitalize(SubPatterns[i]);
2 : TempFilename:=TempFileName+WideLowerCase(SubPatterns[i]);
3 : TempFilename:=TempFileName+WideUpperCase(SubPatterns[i]);
4 : TempFilename:=TempFileName+WideCaseInvert(SubPatterns[i]);
5 : TempFilename:=TempFileName+WideUpperCase(SubPatterns[i][1])+WideLowerCase(WideCopy(SubPatterns[i], 2, Length(SubPatterns[i])-1));
else
begin
ShowMessage('The value of CHANGE_CASE constant is invalid. Check legend for info.');
TimeToExit:=True;
break;
end;
end;
end;
if start_pos < Length(FileNameProcessedPart) then
TempFilename:=TempFileName+WideCopy(FileNameProcessedPart, start_pos, Length(FileNameProcessedPart)-start_pos+1);
if NotAFullMatch then
if CheckIfFullMatch then
begin
if not WideInputQuery('RegEx didn''t match the full filename.', 'Old filename:'+#10+FileName+#10+#10+'Proposed new filename: '+#10+TempFileName+WideExtractFileExt(FileName)+#10+#10+'What should we do?'#10+#10+'Pressing OK button = Rename that file'+#10+'Pressing Cancek button = Skip that file'+#10+'Type '''+BREAK_STRING+''' in the text field to exit the script or '''+FOR_ALL_STRING+''' if you want to continue with all the files.'+#10, Answer) then
exit
else if WideSameText(WideLowerCase(Answer),BREAK_STRING) then
begin
TimeToExit:=True;
exit;
end
else if WideSameText(WideLowerCase(Answer),FOR_ALL_STRING) then
begin
CheckIfFullMatch:=False;
end
else
Answer:=STANDARD_ANSWER;
end;
if SKIP_EXTENTION then
FileName:=TempFileName+WideExtractFileExt(FileName)
else FileName:=TempFileName;
end
else exit;
end.
Enjoy!
Last edited by krtek (2009-08-12 11:31)
Regular Expressions are not as hard to understand as you may think. Check ReNamer's manual or nice Regular Expressions tutorial for more info and start to use full power of applications that use them (like ReNamer, Mp3Tag and so on).
Offline