Help Required - Smart Move and Rename

Please check the FAQ (https://www.xyplorer.com/faq.php) before posting a question...
Post Reply
nerdweed
Posts: 648
Joined: 25 Feb 2012 07:47

Help Required - Smart Move and Rename

Post by nerdweed »

I move lots of files to some folders.

Code: Select all

 $selections = get("SelectedItemsPathNames", "|");  //store
 $move_dir = "$home". "$cat";
 moveto "$move_dir", $selections, , 2;
 $newNames = get("targetitems", "|");
 rename b, "<#1> /s", , $newNames ;
The above code will move the files to a particular folder, regardless of how many files are there in the folder. However; for performance in listing I prefer to have only 1000 files in a directory. What I want to achieve is, if on moving the number of files would exceed 1000, for eg. If there are 990 files and I move additional 15 files (totalling it to 1005), it should move the first 990 and 10 of the remaining 15 files to a subfolder named 1.

On next occurence, it would be moved to 2 and 3 and so on

Code: Select all

 new("FolderLimit", "dir");
 sel f;	//Select files
 sel i;	//Invert selection to get folders
 $num=get("CountSelected");
 renameitem($num, "FolderLimit");
 $newFolder = "$folder\$num";
I am stuck on the important bit of moving those files to sub-folder. Any pointers please

SkyFrontier
Posts: 2341
Joined: 04 Jan 2010 14:27
Location: Pasárgada (eu vou!)

Re: Help Required - Smart Move and Renam

Post by SkyFrontier »

By "next occurrence" you mean a new move operation to the same folder?
So each numbered will have packs of 15? Don't get it. (doable, anyway)

What about...
(-target folder: don't mind quantity)
(new move: if total <= 1000) { move all; }
else total > 1000 (say 2300) { move 1000; folder2 - 1000, folder3 - 300 }
New User's Ref. Guide and Quick Setup Guide can help a bit! Check XYplorer Resources Index for many useful links!
Want a new XYperience? XY MOD - surfYnXoard
-coz' the aim of computing is to free us to LIVE...

nerdweed
Posts: 648
Joined: 25 Feb 2012 07:47

Re: Help Required - Smart Move and Renam

Post by nerdweed »

First Occurence would be when the folder doesn't have any folders and hits the threshold of 1000 file i.e.; it has 1001 files or more (lets says 1010). So, the first 1000 files should be moved to a subfolder named 1. Now the parent folder would have
A subfolder named 1 with 1000 files in it and 10 files

Next Occurence, gradually it will have more than 1000 files as well. So since the subfolder 1 already has 1000 files, the files should be moved to 2 and so on.

No, it won't always be in packs of 15, it can any number.
1. No. of files is less than 1000 and I move enough files to bring the number to 1000 (move 10 files if it has 990 or move 100 files if there are 900 files) - In this case I am ok to move all these files to a new sub-folder or keep it there and let it be addressed on the next run.
2. No. of files is less than 1000 and I move a number of files and the count goes beyond 1000 (move 5 (lot 2) files when it has 999 (lot 1) files or move 500 files (lot 2) when there are 700 files (lot 1) ). - In this case I should be moving exactly 1000 files to a new sub-folder. The already exisiting files (lot 1) should be moved and then enough files from lot 2 should be moved so that exactly 1000 files are moved.

i.e.; if 999 files are there and 5 are moved - it should move the already existing 999 files and 1 from the newly moved 5 files
similarly, if 700 files are there and 500 are moved - it should move the already existing 700 files and 300 from the newly moved 500 files
What about...
(-target folder: don't mind quantity)
Target folder will always have 1000 files as we would create new sub-folders on each occurence
(new move: if total <= 1000) { move all; }
If total is less than 1000 then do nothing
else total > 1000 (say 2300) { move 1000; folder2 - 1000, folder3 - 300 }
Almost correct - first 1000 files will be in folder 1, next 1000 in folder 2, the last 300 would remain in the parent folder until they become a lot of 1000

SkyFrontier
Posts: 2341
Joined: 04 Jan 2010 14:27
Location: Pasárgada (eu vou!)

Re: Help Required - Smart Move and Renam

Post by SkyFrontier »

Is enough to have a single-folder solution? IE, source folder is always "folder X" (per session).
Is this intended to work on a current session only or does it need to survive XY restart?
New User's Ref. Guide and Quick Setup Guide can help a bit! Check XYplorer Resources Index for many useful links!
Want a new XYperience? XY MOD - surfYnXoard
-coz' the aim of computing is to free us to LIVE...

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

Re: Help Required - Smart Move and Renam

Post by highend »

Something like this?

Code: Select all

    $rootPath = "R:\Temp\_test";

    $filesInSubFolder  = 0;
    $filesInRootPath   = listfolder($rootPath, , 1);
    $filesInRootPathNr = gettoken($filesInRootPath, "count", "|");

    if ($filesInRootPathNr > 1000) {
        $latestSubFolder = getpathcomponent(gettoken(formatlist(listfolder($rootPath, , 2), "rn"), 1, "|"), "base");
        if !($latestSubFolder) { new("$rootPath\1", "dir"); $dstFolder = "$rootPath\1"; }
        else { $dstFolder = "$rootPath\$latestSubFolder"; }

        $filesInSubFolder = gettoken(listfolder($dstFolder, , 1), "count", "|");
        if ($filesInSubFolder >= 1000) {
            new("$rootPath\" . $latestSubFolder + 1, "dir");
            $dstFolder = "$rootPath\" . $latestSubFolder + 1;
            $filesInSubFolder = gettoken(listfolder($dstFolder, , 1), "count", "|");
        }
        $filesToMoveNr = ($filesInSubFolder) ? 1000 - $filesInSubFolder : 1000;
        $filesToMove   = getTokenRange($filesInRootPath, 1, $filesToMoveNr, "|");
        moveto $dstFolder, $filesToMove, , 2;
    } else { status "Less than 1000 files in root dir, aborted!", "8B4513", "stop"; } // saddlebrown

function getTokenRange($str, $index=1, $count=1, $sep=" ", $format="") {
    if ($count > 1) {
        $all = gettoken($str, $index, $sep, $format, 2);
        $rem = regexreplace($sep . gettoken($str, $index + $count, $sep, $format, 2), "([\\^$.+*|?(){\[])", "\$1");
        return regexreplace($all, $rem . "$");
    }
    return gettoken($str, $index, $sep, $format);
}
One of my scripts helped you out? Please donate via Paypal

nerdweed
Posts: 648
Joined: 25 Feb 2012 07:47

Re: Help Required - Smart Move and Rename

Post by nerdweed »

Thanks highend. Not exactly what I want (I see that you are processing the subfolders 1,2 etc which isn't needed). I will try to achieve something from this and post back

The new set of files are in a completely different directory (D:\Home\Downloads). The files would be moved to another directory (D:\Documents\Files). I don't need to list the files in the subfolders as they will be created only when 1000 files are there.

Let me explain it this way

1. Folder Structure for D:\Documents\Files
D:\Documents\Files\ --> 500 files

2. I copy a further 490 files
D:\Documents\Files\ --> 990 files (500+490)

3. I move 100 files, which would make the total no of files to be 1090, so the folder structure should become like
D:\Documents\Files\1 --> 1000 files (important bit, the 990 files from step 2 should go in here and 10 files from the remaining 100 that were moved)
D:\Documents\Files --> 90 files

4. I move another 600 files
D:\Documents\Files\1 --> 1000 files (No need to touch this folder)
D:\Documents\Files --> 90 existing files + 600 moved files = 690 files (No more processing required as it is still under 1000)

4. I move additional 500 files
D:\Documents\Files\1 --> 1000 files (No need to touch this folder)
D:\Documents\Files\2 --> 1000 files (690 files from step 5 and 310 files from the newly moved 500 files)
D:\Documents\Files --> 190 files (690 existing files were moved and 310 from the freshly copied files were moved = 690+500-1000)

nerdweed
Posts: 648
Joined: 25 Feb 2012 07:47

Re: Help Required - Smart Move and Rename

Post by nerdweed »

ListFolder was the key and your function was immensely helpful. I have rewritten it as below - Needs to be checked

Edit: removed non working code. Working code in the next post
Last edited by nerdweed on 26 Jul 2015 18:30, edited 1 time in total.

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

Re: Help Required - Smart Move and Rename

Post by highend »

(I see that you are processing the subfolders 1,2 etc which isn't needed)
Mh? I'm only processing the highest subfolder value (1, 2, 3, whatever) and only to count the already existing files in it. E.g. if if there are already 2 subfolders (1, 2) my script doesn't touch nr. 1 in any way but only counts the nr of files in 2.
One of my scripts helped you out? Please donate via Paypal

nerdweed
Posts: 648
Joined: 25 Feb 2012 07:47

Re: Help Required - Smart Move and Rename

Post by nerdweed »

Yes, but counting files in the highest subfolder value isn't required either. With your help, I have managed to get it working

The below code is working as per expectations (though it lagged a little bit on moving it to a sub-folder - don't know why).

Thanks again for helping me out.

Edit: Re-written as a function

Code: Select all

//Destination --> Required, destination folder
//Source --> Optional, if source is not provided, the currently selected files are copied
//Limit --> Optional, number of files per sub-folder. Defaults to 1000

function ltdFileMove($destination = "", $selections = "", $limit = 1000) {
	if (!$destination)	{
		status "Error!! Please provide a destination folder";
		return -1;
	} 
	if (!$selections)	{
		$selections = get("SelectedItemsPathNames", "|");  //store
	}
	
	$countFilesToBeMoved  = gettoken($selections, "count", "|");
	if (!$countFilesToBeMoved) {
		status "No files were selected";
		return -1;
	}
	
	$filesInFolder   = listfolder($destination, , 1, "|");
	$countFilesInFolder = gettoken($filesInFolder, "count", "|");
	
	$countFilesToMoveFromSourceToSubDir = 0;
	$countFilesFollowingMove = $countFilesInFolder + $countFilesToBeMoved;
	
	if ($countFilesFollowingMove > $limit) {
		$latestSubFolder = getpathcomponent(gettoken(formatlist(listfolder($destination, , 2, "|"), "rn"), 1, "|"), "base");
		if !($latestSubFolder) {
			$latestSubFolder = 0;
		}
		
		if ($countFilesInFolder)
		{
			$startIndex = 1;
			while ($countFilesFollowingMove > $limit)
			{
				$latestSubFolder = $latestSubFolder + 1;
				$dstFolder = "$destination\$latestSubFolder" ;
			
				$filesToMove   = getTokenRange($filesInFolder, $startIndex, $limit, "|");
				moveto $dstFolder, $filesToMove, , 2;
				$newNames = get("targetitems", "|");
				rename b, "<#1> /s", , $newNames;
				
				if ($countFilesInFolder >= $limit)	{
					$countFilesFollowingMove = $countFilesFollowingMove - $limit ;
					$countFilesInFolder = $countFilesInFolder - $limit ;
				} else {
					$countFilesFollowingMove = $countFilesFollowingMove - $countFilesInFolder ;
					$countFilesToMoveFromSourceToSubDir = $limit - $countFilesInFolder;
					$countFilesInFolder = 0;
					break;	//Get out of the loop
				}
				$startIndex = $startIndex + $limit;
			}
		}
		
		$startIndex = 1;
		$countFilesToMoveFromSourceToSubDir = $countFilesToMoveFromSourceToSubDir % $limit;
		
		if ($countFilesToMoveFromSourceToSubDir) {
			$filesToMove = getTokenRange($selections, $startIndex, $countFilesToMoveFromSourceToSubDir, "|");
			moveto $dstFolder, $filesToMove, , 2;
			rename b, "<#1> /s", , $newNames ;
			$startIndex = $startIndex + $countFilesToMoveFromSourceToSubDir;
			$countFilesToBeMoved = $countFilesToBeMoved - $countFilesToMoveFromSourceToSubDir;
			$countFilesToMoveFromSourceToSubDir = 0;
		}
		
		while ($countFilesToBeMoved > 0)	{
			if ($countFilesToBeMoved > 1000)	{
				$latestSubFolder = $latestSubFolder + 1;
				$dstFolder = "$destination\$latestSubFolder" ;
			} else {
				$dstFolder = "$destination";
			}
			$filesToMove = getTokenRange($selections, $startIndex, $limit, "|");
			moveto $dstFolder, $filesToMove, , 2;
			$newNames = get("targetitems", "|");
			rename b, "<#1> /s", , $newNames ;
			$countFilesToBeMoved = $countFilesToBeMoved - $limit;
			$startIndex = $startIndex + $limit;
		}
	} else	{
		moveto $destination, $selections, , 2;
		$newNames = get("targetitems", "|");
		rename b, "<#1> /s", , $newNames ;
	}
	return 1;
}

function getTokenRange($str, $index=1, $count=1, $sep=" ", $format="") {
    if ($count > 1) {
        $all = gettoken($str, $index, $sep, $format, 2);
        $rem = regexreplace($sep . gettoken($str, $index + $count, $sep, $format, 2), "([\\^$.+*|?(){\[])", "\$1");
        return regexreplace($all, $rem . "$");
    }
    return gettoken($str, $index, $sep, $format);
}

Post Reply