Page 1 of 2
Search and replace "string" in all folder names.
Posted: 19 Apr 2015 07:54
by stts
Trying to replace a "string" in all the folder and subfolder names in a tree to shorted the path to less than 255 characters. Will XY plorer do this? I been doing this to all files, but dont know how to do it for directory names.
Re: Search and replace "string" in all folder names.
Posted: 19 Apr 2015 10:15
by bdeshi
Code: Select all
$src = inputfolder(<curpath>, 'pick root folder');
$lst = formatlist(folderreport('dirs', 'r', $src, 'r', , '|'), 'v', '|'); //invert dirlist so deeper folders are processed first
$lst = $lst.'|'.$src ; //inclusive of parent folder
$pattern = input('Enter the string to remove', 'optionally enter a replacement: string/replace. Suffix \ to replace case-sensitively,eg, StR/RepLaCe\',,'s');
$remstr = gettoken($pattern, 1, '/');
$rplstr = gettoken($pattern, 2, '/');
rename 's', $remstr . '/' . $rplstr, , $lst, 1;
//comment out the rename command (the line above) before uncommenting following codeblock.
//vica versa, comment out the following codeblock before uncommenting the rename command.
/*
foreach ($itm, $lst, '|') {
$newname = replace(gettoken($itm, -1, '\'), $remstr, $rplstr);
renameitem($newname, $itm, 1+2+4); //prompt on name-collision
}
*/
#1001; //refresh
A folder picker dlg will open. Select the parent of all to-rename folders. Then in the next inputbox enter the string to remove plainly. You can also opt to replace it with something else. Say, to remove 'verylongstr', simply enter verylongstr. To replace it with 'ShortStr', enter verylongstr/ShortStr. Note: suffix a \ at the very end of whole pattern to replace case-sensitively. verylongstr/ShortStr != VeryLongStr/ShortStr\
All subfolders
and the parent folder will be renamed.
Re: Search and replace "string" in all folder names.
Posted: 19 Apr 2015 11:13
by stts
Thank you very much. I will try this out.
It worked perfectly. Saves me a ton of renameing of all the massive file names with useless info in the names.
Re: Search and replace "string" in all folder names.
Posted: 21 Apr 2015 09:20
by stts
When making search and replace changes to these directories and subdirectories, can these changes be done to the files in the directories as well?
Also, can a list of changes be entered seperated by comma? For example:
2015/(2015),2014/(2014),2013/(2013),2012/(2012),etc. Then all directories and the files in them can be cleaned up in one shot no matter what date they have.
Re: Search and replace "string" in all folder names.
Posted: 21 Apr 2015 12:15
by highend
Patterns must be separated by "|" (without quotation marks), not by a comma!
Reason: A "|" can't be part of a folder- / filename so it's safe to use it as a delimiter. Imagine that you want to replace a ","...
Code: Select all
$src = inputfolder(<curpath>, 'Pick root folder');
$lst = formatlist(folderreport('items', 'r', $src, 'r', , '|'), 'v', '|'); //invert dirlist so deeper folders are processed first
$lst = $lst.'|'.$src ; //inclusive of parent folder
$patterns = input('Enter the string to remove', "Optionally enter a replacement: string/replace. Suffix \ to replace case-sensitively, eg.: StR/RepLaCe\<crlf 2>Separate additional patterns with a | character", ,'s');
if ($patterns) {
if (gettoken($patterns, "count", "|") == 1) {
$remstr = gettoken($patterns, 1, '/');
$rplstr = gettoken($patterns, 2, '/');
rename 's', $remstr . '/' . $rplstr, , $lst, 1;
} else {
foreach ($itm, $lst, '|') {
$newname = $itm;
foreach($pattern, $patterns, "|") {
$remstr = gettoken($pattern, 1, '/');
$rplstr = gettoken($pattern, 2, '/');
$newname = replace(gettoken($newname, -1, '\'), $remstr, $rplstr);
}
renameitem($newname, $itm, 1+2+4); //prompt on name-collision
}
}
#1001; //refresh
}
Re: Search and replace "string" in all folder names.
Posted: 21 Apr 2015 13:42
by stts
Cool. This makes it alot easier to weed the trash out of massive file names. But it ran into file names with access denied during the renameitem process. Can the error list which files it could not access? It looks like lots of files were renamed, but its difficult to see where it stopped at. Especially when the files renamed count doesnt display any more. The count displayed fine in XYplorer on the first version of this script. I moved #1001; to after the last bracket, but it still wont display the count of names modified.
Re: Search and replace "string" in all folder names.
Posted: 21 Apr 2015 14:00
by highend
Untested...
Code: Select all
$src = inputfolder(<curpath>, 'Pick root folder');
$lst = formatlist(folderreport('items', 'r', $src, 'r', , '|'), 'v', '|'); //invert dirlist so deeper folders are processed first
$lst = $lst.'|'.$src ; //inclusive of parent folder
$patterns = input('Enter the string to remove', "Optionally enter a replacement: string/replace. Suffix \ to replace case-sensitively, eg.: StR/RepLaCe\<crlf 2>Separate additional patterns with a | character", ,'s');
if ($patterns) {
$unrenamedItems = "";
if (gettoken($patterns, "count", "|") == 1) {
$remstr = gettoken($patterns, 1, '/');
$rplstr = gettoken($patterns, 2, '/');
rename 's', $remstr . '/' . $rplstr, , $lst, 1;
} else {
foreach ($itm, $lst, '|') {
$newname = $itm;
foreach($pattern, $patterns, "|") {
$remstr = gettoken($pattern, 1, '/');
$rplstr = gettoken($pattern, 2, '/');
$newname = replace(gettoken($newname, -1, '\'), $remstr, $rplstr);
}
$output = renameitem($newname, $itm, 1+2+4); //prompt on name-collision
if !($output) { $unrenamedItems = $unrenamedItems . "$itm<crlf>"; }
}
}
if ($unrenamedItems) { text "These items could not be renamed:<crlf 2>$unrenamedItems"; }
#1001; //refresh
}
If you see folder names in that list it's probably because a locked file was in it (even if the folder name itself would not have been changed).
It's currently implemented only for multiple patterns. For a single pattern it's probably faster to use rename on all items at once. This could be changed by looping through all files regardless if a single or multiple pattern is used...
This would look like this:
Code: Select all
$src = inputfolder(<curpath>, 'Pick root folder');
$lst = formatlist(folderreport('items', 'r', $src, 'r', , '|'), 'v', '|'); //invert dirlist so deeper folders are processed first
$lst = $lst.'|'.$src ; //inclusive of parent folder
$patterns = input('Enter the string to remove', "Optionally enter a replacement: string/replace. Suffix \ to replace case-sensitively, eg.: StR/RepLaCe\<crlf 2>Separate additional patterns with a | character", ,'s');
if ($patterns) {
$unrenamedItems = "";
foreach ($itm, $lst, '|') {
$newname = $itm;
foreach($pattern, $patterns, "|") {
$remstr = gettoken($pattern, 1, '/');
$rplstr = gettoken($pattern, 2, '/');
$newname = replace(gettoken($newname, -1, '\'), $remstr, $rplstr);
}
$output = renameitem($newname, $itm, 1+2+4); //prompt on name-collision
if !($output) { $unrenamedItems = $unrenamedItems . "$itm<crlf>"; }
}
if ($unrenamedItems) { text "These items could not be renamed:<crlf 2>$unrenamedItems"; }
#1001; //refresh
}
Re: Search and replace "string" in all folder names.
Posted: 21 Apr 2015 14:08
by stts
Cool. There was 3 files it could not access. But if there was 100 for some reason, I would have to click continue an infinite number of times before I finally got a listing of the locked files. The only other choice was cancel script. And there is still no count of number of names modified.
Re: Search and replace "string" in all folder names.
Posted: 21 Apr 2015 15:03
by highend
The command status... isn't always reliable (it can easily overwritten by xy itself).
Code: Select all
$src = inputfolder(<curpath>, 'Pick root folder');
$lst = formatlist(folderreport('items', 'r', $src, 'r', , '|'), 'v', '|'); //invert dirlist so deeper folders are processed first
$lst = $lst.'|'.$src ; //inclusive of parent folder
$patterns = input('Enter the string to remove', "Optionally enter a replacement: string/replace. Suffix \ to replace case-sensitively, eg.: StR/RepLaCe\<crlf 2>Separate additional patterns with a | character", ,'s');
if ($patterns) {
$count = 0;
$countAll = gettoken($lst, "count", "|");
$unrenamedItems = "";
foreach ($itm, $lst, '|') {
$oldname = gettoken($itm, -1, '\');
foreach($pattern, $patterns, "|") {
$remstr = gettoken($pattern, 1, '/');
$rplstr = gettoken($pattern, 2, '/');
$newname = replace(gettoken($oldname, -1, '\'), $remstr, $rplstr);
}
if ($newname != $oldname) {
$output = renameitem($newname, $itm, 1+2+4); //prompt on name-collision
if !($output) { $unrenamedItems = $unrenamedItems . "$itm<crlf>"; }
else { $count++; }
}
}
#1001; //refresh
$message = ($unrenamedItems) ? "<crlf 3>These items could not be renamed:<crlf 2>$unrenamedItems" : "";
text "Items renamed: $count of $countAll$message";
}
I would have to click continue an infinite number of times before I finally got a listing of the locked files.
Nothing we can do about until Don changes the renameitem() function...
Get rid of locked files before^^
Re: Search and replace "string" in all folder names.
Posted: 21 Apr 2015 16:20
by stts
Yup, I fixed the locked files. And thanks for making this function. Its very useful and gives enough feedback to deal with problems that crop up. Ill try it on a huge drive after I test it out more. But it seems good the way it is.

Re: Search and replace "string" in all folder names.
Posted: 21 Apr 2015 17:11
by hermhart
highend,
This seems to work pretty slick. When I was testing this, I noticed that when you have multiple renames using the "|", it only seems to change the last one of the list. Also, could this be made to let you choose whether you want to perform the action on Folders, Files or Folders and Files?
Re: Search and replace "string" in all folder names.
Posted: 21 Apr 2015 18:46
by highend
When I was testing this, I noticed that when you have multiple renames using the "|", it only seems to change the last one of the list
Fixed.
Also, could this be made to let you choose whether you want to perform the action on Folders, Files or Folders and Files?
Added.
Code: Select all
$src = inputfolder(<curpath>, 'Pick root folder');
$type = inputselect("Choose if you want to process files, folders or both...", "Files|Folders|Files & Folders", "|", 4+32+128, , 350, 300);
if ($type == 1) { $type = "files"; }
elseif ($type == 2) { $type = "dirs"; }
elseif ($type == 3) { $type = "items"; }
$lst = formatlist(folderreport($type, 'r', $src, 'r', , '|'), 'v', '|') . "|$src"; // Invert dirlist so deeper folders are processed first + include root folder
$patterns = input('Enter the string to remove', "Optionally enter a replacement: string/replace. Suffix \ to replace case-sensitively, eg.: StR/RepLaCe\<crlf 2>Separate additional patterns with a | character", ,'s');
if ($patterns) {
$count = 0;
$countAll = gettoken($lst, "count", "|");
$unrenamedItems = "";
foreach ($itm, $lst, '|') {
$oldname = gettoken($itm, -1, '\');
$newname = $oldname;
foreach($pattern, $patterns, "|") {
$remstr = gettoken($pattern, 1, '/');
$rplstr = gettoken($pattern, 2, '/');
$newname = replace($newname, $remstr, $rplstr);
}
if ($newname != $oldname) {
$output = renameitem($newname, $itm, 1+2+4); //prompt on name-collision
if !($output) { $unrenamedItems = $unrenamedItems . "$itm<crlf>"; }
else { $count++; }
}
}
#1001; //refresh
$message = ($unrenamedItems) ? "<crlf 3>These items could not be renamed:<crlf 2>$unrenamedItems" : "";
text "Items renamed: $count of $countAll$message";
}
Re: Search and replace "string" in all folder names.
Posted: 21 Apr 2015 19:25
by hermhart
highend,
Thank you for the fix and the additional options, that is absolutely awesome!

Re: Search and replace "string" in all folder names.
Posted: 22 Apr 2015 11:49
by stts
A bug seems to have creeped into it. No matter what I do, mouse clicked on menu choices, entered 1or2or3, or just spelled out any of the choices, $type returns value of zero and none of the if statements get executed.
I tried to fix it but I dont understand the inputselect command. You have it autoselecting the first item. So it should never return a value of zero. Im using version 12.3 of XYplorer. Maybe thats why inputselect command dont seem to work for me.
Re: Search and replace "string" in all folder names.
Posted: 22 Apr 2015 11:54
by highend
This isn't "a bug", it's your (absolutely) outdated XY version. Yours is about two years old and a few things happened to this command in the meantime.
At least v14.50.0208 should be used because it fixed a major bug returning the correct index.