Search and replace "string" in all folder names.

Please check the FAQ (https://www.xyplorer.com/faq.php) before posting a question...
stts
Posts: 18
Joined: 13 Apr 2006 06:33

Search and replace "string" in all folder names.

Post 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.

bdeshi
Posts: 4256
Joined: 12 Mar 2014 17:27
Location: Asteroid B-612
Contact:

Re: Search and replace "string" in all folder names.

Post 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.
Icon Names | Onyx | Undocumented Commands | xypcre
[ this user is asleep ]

stts
Posts: 18
Joined: 13 Apr 2006 06:33

Re: Search and replace "string" in all folder names.

Post 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.

stts
Posts: 18
Joined: 13 Apr 2006 06:33

Re: Search and replace "string" in all folder names.

Post 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.

highend
Posts: 14950
Joined: 06 Feb 2011 00:33
Location: Win Server 2022 @100%

Re: Search and replace "string" in all folder names.

Post 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
    }
One of my scripts helped you out? Please donate via Paypal

stts
Posts: 18
Joined: 13 Apr 2006 06:33

Re: Search and replace "string" in all folder names.

Post 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.

highend
Posts: 14950
Joined: 06 Feb 2011 00:33
Location: Win Server 2022 @100%

Re: Search and replace "string" in all folder names.

Post 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
    }
One of my scripts helped you out? Please donate via Paypal

stts
Posts: 18
Joined: 13 Apr 2006 06:33

Re: Search and replace "string" in all folder names.

Post 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.

highend
Posts: 14950
Joined: 06 Feb 2011 00:33
Location: Win Server 2022 @100%

Re: Search and replace "string" in all folder names.

Post 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^^
One of my scripts helped you out? Please donate via Paypal

stts
Posts: 18
Joined: 13 Apr 2006 06:33

Re: Search and replace "string" in all folder names.

Post 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. :)

hermhart
Posts: 244
Joined: 13 Jan 2015 18:41

Re: Search and replace "string" in all folder names.

Post 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?
Windows 11 Pro; 100% scaling

highend
Posts: 14950
Joined: 06 Feb 2011 00:33
Location: Win Server 2022 @100%

Re: Search and replace "string" in all folder names.

Post 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";
    }
One of my scripts helped you out? Please donate via Paypal

hermhart
Posts: 244
Joined: 13 Jan 2015 18:41

Re: Search and replace "string" in all folder names.

Post by hermhart »

highend,

Thank you for the fix and the additional options, that is absolutely awesome! :appl:
Windows 11 Pro; 100% scaling

stts
Posts: 18
Joined: 13 Apr 2006 06:33

Re: Search and replace "string" in all folder names.

Post 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.

highend
Posts: 14950
Joined: 06 Feb 2011 00:33
Location: Win Server 2022 @100%

Re: Search and replace "string" in all folder names.

Post 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.
One of my scripts helped you out? Please donate via Paypal

Post Reply