Creating folders based on filename, then moving files inside

Discuss and share scripts and script files...
Post Reply
Biggynuff
Posts: 108
Joined: 13 May 2010 14:08

Creating folders based on filename, then moving files inside

Post 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

highend
Posts: 13309
Joined: 06 Feb 2011 00:33

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

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

j_c_hallgren
XY Blog Master
Posts: 5824
Joined: 02 Jan 2006 19:34
Location: So. Chatham MA/Clearwater FL
Contact:

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

Post 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!
Still spending WAY TOO much time here! But it's such a pleasure helping XY be a treasure!
(XP on laptop with touchpad and thus NO mouse!) Using latest beta vers when possible.

Biggynuff
Posts: 108
Joined: 13 May 2010 14:08

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

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

yusef88
Posts: 1126
Joined: 28 Jan 2013 03:50
Location: Windows 8.1 32-bit

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

Post by yusef88 »

hi everyone
can the script move files with similar names into one folder?
Attachments
1.png
1.png (4.7 KiB) Viewed 7667 times
2.png
2.png (6.27 KiB) Viewed 7667 times

kko
Posts: 7
Joined: 15 Apr 2016 05:35

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

Post 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;
}

highend
Posts: 13309
Joined: 06 Feb 2011 00:33

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

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

starstuff
Posts: 29
Joined: 07 May 2015 15:30

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

Post 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;
   }

highend
Posts: 13309
Joined: 06 Feb 2011 00:33

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

Post by highend »

This should work:

Code: Select all

    setting "BackgroundFileOps", 0;
    foreach($item, <get "SelectedItemsNames" |>) {
        moveas "*.?", "<curpath>\" . gettoken(gpc($item, "base"), 1, " - "), $item;
    }
One of my scripts helped you out? Please donate via Paypal

angang
Posts: 5
Joined: 17 Sep 2016 03:50

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

Post 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

highend
Posts: 13309
Joined: 06 Feb 2011 00:33

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

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

angang
Posts: 5
Joined: 17 Sep 2016 03:50

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

Post by angang »

It works like a charm !
Thank you so much highend :tup: :appl:

Post Reply