Unflatten a folder

Please check the FAQ (https://www.xyplorer.com/faq.php) before posting a question...
Post Reply
pdupreez
Posts: 19
Joined: 15 Aug 2018 11:40

Unflatten a folder

Post by pdupreez »

After a lot of cleaning and de-duplication of my music folders, I now have a flat folder with all my duplicate files. I am not yet ready to delete these (50k+ files) just in case I need to fill an album which I have inadvertently deleted a file or two. Dealing with a folder with 50k+ files is however a pain in the neck, even with XYplorer and 32GB RAM.

I would like to unflatten the folder into an alphabetical structure, using the first element in the name as a start i.e.

1 song for you.mp3
My first song.mp3
The second Song.mp3
Free songs in a row.mp3

Should end up as

Base folder:\#\1 song for you.mp3
Base folder:\F\Free songs in a row.mp3
Base folder:\M\My first song.mp3
Base folder:\T\The second Song.mp3

Eventually I will end up with a structure that stretches
Base folder:\# (for anything not alphabetical)
Base folder:\A\files.xyz
Base folder:\B\files.xyz
Base folder:\C\files.xyz
.
.
.
Base folder:\Z\files.xyz

jupe
Posts: 2794
Joined: 20 Oct 2017 21:14
Location: Win10 22H2 120dpi

Re: Unflatten a folder

Post by jupe »

Here is one way to do it, it might not be the fastest way though, but if you want to try it anyway just goto the main folder then run it, it has a built in preview although be prepared for it to take a little while before the preview window shows up with that amount of files.

Code: Select all

	$dest = "";
	setting "HideFoldersInList", 1;
	foreach($file, <get itemsnames |>) {
	  $prefix = recase(substr($file, 0, 1), "u");
	  if $prefix LikeI "[A-Z]" {
		 $dest .= $prefix . "\" . $file . "|";
	  } else {
		 $dest .= "#\" . $file . "|";
	  }
	}
	rename l, trim($dest, "|"), "p", <allitems |>;
This setting needs to be enabled for it to work though:
Configuration | General | Sort and Rename | Rename | Allow move on rename

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

Re: Unflatten a folder

Post by highend »

Ok, here is how I'd do it (as always, heavy regex involved, be aware!)

Code: Select all

    setting "AutoRefresh", 0;
    $items = listfolder(, , 1+4, <crlf>);
    $prefixes = recase(formatlist(regexmatches($items, "^[a-z]"), "sd"), "u");
    foreach($prefix, $prefixes, , "e") { if (exists($prefix) != 2) { new($prefix, "dir"); } }

    $cItems = regexmatches($items, "^[a-z].+?(?=\r?\n|$)", <crlf>);
    $oItems = regexmatches($items, "^(?![a-z]).+?(?=\r?\n|$)", <crlf>);

    $oRItems = replace(regexreplace($oItems, "^(.+?)(?=\r?\n|$)", "#\$1"), <crlf>, "|");
    $cRItems = replace(regexreplace($cItems, "^([a-z])(.+?)(?=\r?\n|$)", "$1\$1$2"), <crlf>, "|");

    rename "l", $oRItems, , replace(regexreplace($oItems, "^(.+?)(?=\r?\n|$)", "<curpath>\$1"), <crlf>, "|");
    rename "l", $cRItems, , replace(regexreplace($cItems, "^(.+?)(?=\r?\n|$)", "<curpath>\$1"), <crlf>, "|");
It only needs at max 26 calls to create a new folder (a-z, depending on if you have files beginning with this char)
and then there are only two renames, one for all items that do not begin with a-z and one more for all others...

Unfortunately the regex engine does not support uppercasing matches, so creating the folders can't be avoided
if only two renames should be used...
One of my scripts helped you out? Please donate via Paypal

Post Reply