Unflatten a folder

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

Unflatten a folder

Post by pdupreez » 21 Aug 2018 14:40

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

Posts: 1285
Joined: 20 Oct 2017 21:14
Location: 2004 x64

Re: Unflatten a folder

Post by jupe » 21 Aug 2018 15:01

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

Posts: 9101
Joined: 06 Feb 2011 00:33

Re: Unflatten a folder

Post by highend » 21 Aug 2018 17:07

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 or paypal_donate (at) stdmail (dot) de

Post Reply