Page 1 of 1

Creating folders based on filename, then moving files inside

Posted: 20 Apr 2013 16:35
by Biggynuff
Hi all,

I couldn't find a script for this so I made one, hope it's of use to someone. With simple fixing up it could be used for all sorts of things (long lists of Jpg's from holiday snaps comes to mind)

So, I have a folder with 6, 903 sound files (.wav's) and I wanted to move them all into nice and neat organized folders. The files are in sets of anywhere from 20 to 65 files, each having a prefixed pattern to identify them as belonging to the set.

For instance:

SynthRock - drumbeat01.wav
SynthRock - shakers.wav
SynthRock - piano solo.wav
HeavyMetal - rythm chords.wav
HeavyMetal - lead.wav
Trance - arp01.wav
Trance - arp02.wav

I wanted to move all the files prefixed with SynthRock into a folder of that name, all files prefixed with HeavyMetal into a folder of that name etc. etc. etc. So I'd have this:

(folder) SynthRock >
SynthRock - drumbeat01.wav
SynthRock - shakers.wav
SynthRock - piano solo.wav

(folder) HeavyMetal >
HeavyMetal - rythm chords.wav
HeavyMetal - lead.wav

(folder) Trance >
Trance - arp01.wav
Trance - arp02.wav

I could have spent a week doing this by hand, but the thought of eventual brain numbing suicide made me realise I should invest the time in writing a script. Not so easy for someone as daft at this sort of thing as me! Took quite some trial and error, but I learned a lot from my mistakes. I've not had a go at any scripting for ages, but anyway here goes:

Code: Select all

foreach($ITEM, get("SelectedItemsNames", "|") ){
   
    $B = getpathcomponent($ITEM, "base");
    $Bshort = regexreplace($B, ^(.*)( - )(.*), $1);
        if (!exists("<curpath>\$Bshort")) {
        new("<curpath>\$Bshort", "dir");
        }
    selectitems "$ITEM";   
    moveto "<curpath>\$Bshort", , , ;
   
  }
Basically, it just runs through the list of sected files (in my case, the whole folder full of them) and gets the file/path details for each of them.

It then does a simple regex find and replace to look for the pattern and to split off the filename prefix. In my case this was " - " which seperates the first part (what I wanted for the folder name) from the rest. With my files this was easy and the regex I used was straightforward. You'll need to change the pattern here to match what you have and it may not be quite so easy or forgiving.

Following this it checks to see if a folder by the required name already exists. If it does, skip it, if not create it.

Then it selects the original file again (this stumped me for ages as the focus jumped to the newly created folder. Caused me headache for half an hour til I worked it out!). Once selected the file is moved into the corresponding folder.

The loop loops, files continue to get moved and I saved myself a whole load of pain and clicking. Wonderful.

Actually, I didn't save myself anything really, Don did by creating this software. I've no idea how I could get by on a computer everyday without XY. It's incredible.

Note: I am not a good programmer, I hash things up until they work so someone will no doubt come up with something much better.

ALWAYS test on a few files you don't need (copy some?) first before use on your really important stuff.

It worked for me, did the job flawlessly and saved me a headache.

Hope it helps someone

Re: Creating folders based on filename, then moving files in

Posted: 20 Apr 2013 16:57
by highend
I wouldn't use a regex for this kind of task, a simple gettoken does it as well.

And you don't need to select all the files to move them afterwards, just use moveas in your script.

E.g. like:

Code: Select all

	foreach($ITEM, get("SelectedItemsNames", "|") ) {
    	$Bshort = gettoken(getpathcomponent($ITEM, "base"), 1, " - ");
    	if (!exists("<curpath>\$Bshort")) {
        	new("<curpath>\$Bshort", "dir");
    	}
    	moveas "*.?", "<curpath>\$Bshort", $ITEM;
	}

Re: Creating folders based on filename, then moving files in

Posted: 20 Apr 2013 17:41
by j_c_hallgren
Biggynuff wrote:Note: I am not a good programmer, I hash things up until they work so someone will no doubt come up with something much better.
Back when I was learning programming in junior college 1976-77, I recall a Fortran assignment that took me about 20-25 lines of code...someone else in class asked me for help because theirs wasn't working...I looked at it and wondered: How did they get SO much code for such a simple task? They had about 100+ lines of code...switches everywhere and all kinds of junk...and...they couldn't even explain what some of it did! That's a sure sign of a bad programmer!

I learned most of my tricks to efficient coding in that language and others by reading other people's code and seeing what I could extract as being a good solution to problem...plus...by knowing the ENTIRE language, I had all the commands and options available...so I'd say that as long as you're willing to learn from others, that's how you become a good programmer!

Re: Creating folders based on filename, then moving files in

Posted: 20 Apr 2013 17:53
by Biggynuff
Thanks so much for the comments and the help. It worked for me but I KNEW there had to be some improvements! :D

I'm really grateful.

I'll go over the new code again and play around. Have some ideas for selecting multiple files (photo's, whatever) then renaming and moving to a new correctly named folder all at the click of a button.

Wow, sometimes I can't believe what we can do with this software.

Re: Creating folders based on filename, then moving files in

Posted: 12 Jul 2015 04:51
by yusef88
hi everyone
can the script move files with similar names into one folder?

Re: Creating folders based on filename, then moving files in

Posted: 24 Apr 2016 03:39
by kko
I've been using highland's version of this script for a while :tup:, my only issue was the more files you had the longer it would take to move each one individually.

I came up with this to work around that issue. Its possible that there is a better way to do it, but this can move 2k files into 20 folders in less than 30 seconds.

Be warned, it currently sorts all items in the current folder. Previously you had to select the items.

Code: Select all

 $separator = input("Type the file name separator",
 "Just the separator, e.g. File are name 'Prefix-SubPrefix-001.txt'
 the separator would be the -" , "-");
 $separatorIndex = input("What index/position should we use?",
 "e.g. Using 'Prefix-SubPrefix-001.txt', 1 = Prefix, 2 = SubPrefix" , "2");
 $i = 1; $iMax = foldersize(,"<f>", 0);
 while (listfolder(,, 1) != "") {
   $baseSep = getBase($separator, $separatorIndex);
   moveBySeparator($baseSep, $separator, $separatorIndex);
   if($i >= $iMax) {break;} //failsafe
   $i++;
 }

function getBase($sep, $sepIndex) {
   foreach($item, listfolder(,, 1) ) {
    return gettoken(getpathcomponent($item, "base"), $sepIndex, $sep);
   }
}

function moveBySeparator($base, $sep, $sepIndex) {
   if ($sepIndex != 1) {$needle = $sep . $base . $sep;}
   else {$needle = $base . $sep;}
   $items = listfolder(, $needle, 1);
   if (!exists("<curpath>\$base")) {
    new("<curpath>\$base", "dir");
   }
   moveas "*.?", "<curpath>\$base", $items;
}

Re: Creating folders based on filename, then moving files in

Posted: 25 Apr 2016 18:13
by highend
More speed?

Mh... This one moved 2000 files (100 files per 20 folders) in ~6,6 seconds on a 2,5 SATA-III Harddisk

Yeah, I know, TheQwerty hates modified lists but nevertheless:

I left the time measurement code in for testing purposes...
I didn't test this with foreign characters so be warned when you try it :)

Code: Select all

    $start = now("msecs");
    $separator = " - ";
    $files = listfolder(, , 1+4, <crlf>);
    setting "AutoRefresh", 0;
    setting "WatchDuringFileOp", 0;
    while ($files) {
        $firstInList = gettoken($files, 1, <crlf>);
        if (strpos($firstInList, $separator) == -1) {
            $files = regexreplace($files, regexEscape($firstInList) . ".*(\r?\n|$)");
            continue;
        }
        $similarNames = "";
        $shortName = gettoken($firstInList, 1, " - ");
        $similarNames = regexmatches($files, regexEscape($shortName . $separator) . ".*?(?=$)", <crlf>);
        if (!exists("<curpath>\$shortName")) { new("<curpath>\$shortName", "dir"); }
        moveas "*.?", "<curpath>\$shortName", replace($similarNames, <crlf>, "|");
        $files = regexreplace($files, regexEscape($shortName . $separator) . ".*(\r?\n|$)");
    }
    $duration = now("msecs") - $start;
    text $duration . " msecs";
    end 1==1;

function regexEscape($string) {
    return regexreplace($string, "([\\^$.+*|?(){\[])", "\$1");
}

Re: Creating folders based on filename, then moving files in

Posted: 03 Jun 2016 05:50
by starstuff
hi highend,

im using your script moving folders based on filename (the code i use is at the bottom), im having some problems when using it with more than 20 files at a time,

i test it to see if i can sort the many files in one go, but i experience some problems like some files are not process, some files are missing ( this is maybe because it was already moved),

ths script work as expected, it moves the files with same name in its own folder and its fast! :tup: , could the script be enhanced more to accommodate >20 files at once?

TIA!

Code: Select all

   foreach($ITEM, get("SelectedItemsNames", "|") ) {
       $Bshort = gettoken(getpathcomponent($ITEM, "base"), 1, " - ");
       if (!exists("<curpath>\$Bshort")) {
           new("<curpath>\$Bshort", "dir");
       }
       moveas "*.?", "<curpath>\$Bshort", $ITEM;
   }

Re: Creating folders based on filename, then moving files in

Posted: 03 Jun 2016 07:14
by highend
This should work:

Code: Select all

    setting "BackgroundFileOps", 0;
    foreach($item, <get "SelectedItemsNames" |>) {
        moveas "*.?", "<curpath>\" . gettoken(gpc($item, "base"), 1, " - "), $item;
    }

Re: Creating folders based on filename, then moving files inside

Posted: 16 Jul 2019 06:56
by angang
Hello,

I need to create in current dir new folders based based on name of folders and then move the original folders (including files) in the new folders

Examples :
[39 Clocks] - Zoned - [2009]
[100% Whole Wheat] - Ice, Fire & Desire - [1978]

Should go in current dir

[39 Clocks]
[39 Clocks] - Zoned - [2009]

[100% Whole Wheat]
[100% Whole Wheat] - Ice, Fire & Desire - [1978]


Could you help me ?

Thanks

Re: Creating folders based on filename, then moving files inside

Posted: 16 Jul 2019 07:11
by highend
That's just a simple variation of the last posted script...

Code: Select all

    setting "BackgroundFileOps", 0;
    foreach($item, <get "SelectedItemsNames" |>) {
        moveas "*.?", "<curpath>\" . gettoken($item, 1, "]") . "]", $item;
    }

Re: Creating folders based on filename, then moving files inside

Posted: 18 Jul 2019 01:23
by angang
It works like a charm !
Thank you so much highend :tup: :appl: