Breaking up a folder into smaller folders...

I want to know if this exists before I write it myself.

I want to choose (or drop) a folder and have it move files (in order of modification date) into newly created, sequentially numbered folders of a specified size. This would be for backing up large hi-res photos onto DVDs.

AppleScript: 1.9.3
Browser: Safari 312
Operating System: Mac OS X (10.3.9)

A major consideration for this would be to look in the finder dictionary to see if “sort by modification date” is available.

My Finder dictionary lists

When I wrote a script to rename files I had to use a custom sort handler to sort by mod date (written by Nigel Garvey, thanks as always). If you run into this issue I can post it for you.
SC

The Finder’s ‘sort’ command seems to have been reinstated in Tiger. But it no longer takes a reference as its parameter; it has to be a list.

-- OS 8/9 sytax:
tell application "Finder"
	sort every item of folder myFolder by modification date
end tell

-- Tiger syntax:
tell application "Finder"
	sort (get every item of folder myFolder) by modification date
end tell

--> In both cases, the result is a sorted list of Finder references,
--> from the most recently modified item to the oldest.

The sorting isn’t that big of a deal. If I really needed it, I’d do it myself, it was really more of an afterthought.

bump :slight_smile:

I could do with a reply to this one. I’m trying to do the same thing… divide up a 100+GB Client folder backup into uniquely named folders no bigger than 8GB. So that I can burn them happily onto a dual layer DVD+R’s and then catalogue them in Portfolio.

I’m running Tiger 10.4.1

tia

Dave

This might get someone started who has more knowledge of allocation blocks and CD/DVD capacities than I have. At the top of the splitFolder() handler, allocBlocks should be set to the size (in bytes) of the allocation blocks on the target medium, and psLimit should be set to that times the number of blocks available for use.

on run
	splitFolder(choose folder)
end run

on open droppedItems
	tell application "Finder"
		repeat with thisItem in droppedItems
			if class of (item thisItem) is folder then my splitFolder(thisItem)
		end repeat
	end tell
end open

on splitFolder(sourceFolder)
	set allocBlocks to 4096 -- assumes multiples of 4K
	set psLimit to 149248 * allocBlocks -- sort out your CD/DVD capacity here
	
	-- On systems prior to Tiger, an external sort routine's required.
	-- This one's at <http://scriptbuilders.net/files/findersort0.6.html>
	-- I keep it in a folder called "Libraries" in my Scripts folder.
	set sortF to (load script file ((path to scripts folder as Unicode text) & "Libraries:FinderSort().scpt"))
	
	tell application "Finder"
		-- Make a new folder on the desktop to hold the smaller, numbered folders.
		set sourceFolder to folder sourceFolder
		set splitFolder to (make new folder at desktop with properties {name:"Split of " & (name of sourceFolder)})
		
		-- Sort the files by modification date (youngest -> oldest).
		set Fref to a reference to every file of sourceFolder
		tell sortF to set sortedFiles to its FinderSort(Fref, "modification date")
		
		-- Start the folder numbers at 1001. (Only the last three digits used.)
		set folderNumber to 1001
		-- Go through the file list (oldest -> youngest), calculating
		-- their cumulative 'physical size' on the other medium.
		set ps to 0
		set j to (count sortedFiles)
		repeat with i from j to 1 by -1
			set thisFile to item i of sortedFiles
			set thisSize to thisFile's size
			repeat while (thisSize is missing value)
				set thisSize to thisFile's size
			end repeat
			set ps to ps + (my quantiseUp(thisSize, allocBlocks))
			
			-- If the 'physical size' limit's reached, 
			-- create a numbered folder and move the files that fit to it.
			if (ps is greater than or equal to psLimit) then
				my moveFiles(sortedFiles, i + 1, j, folderNumber, splitFolder)
				set folderNumber to folderNumber + 1
				set ps to 0
				set j to i
			end if
		end repeat
		-- At the end, move the remaining files to a new, numbered folder.
		my moveFiles(sortedFiles, i, j, folderNumber, splitFolder)
	end tell
	tell application (path to frontmost application as Unicode text)
		display dialog "Done!" buttons {"OK"} default button 1 with icon note
	end tell
end splitFolder

(* Create a numbered folder and move the relevant files to it. *)
on moveFiles(sortedFiles, i, j, folderNumber, splitFolder)
	tell application "Finder"
		set newFolder to (make new folder at splitFolder with properties {name:text 2 thru 4 of (folderNumber as Unicode text)})
		move items i thru j of sortedFiles to newFolder
	end tell
end moveFiles

(* Round up to nearest multiple of q *)
-- From aRounderRound, <http://scriptbuilders.net/files/arounderround1.3.html>
on quantiseUp(n, q)
	if q < 0 then set q to -q
	tell n div q * q
		if it < n then return it + q
		it
	end tell
end quantiseUp

What a STAR Nigel,

I’ve not tried your advice yet but appears to cover all the angles. This should make one of my most teadious jobs seriously more bearable.

Thanks for the help

Dave

Hmmm. That ps shouldn’t be reset to 0 when the files are moved, but to the the physical size value for the current file (which is included in the next group). I’ve also been assuming (fairly reasonably) that no single file will in itself be too big to go on a CD or DVD. But here’s what I hope is a more robust version.

on run
	splitFolder(choose folder)
end run

on open droppedItems
	tell application "Finder"
		repeat with thisItem in droppedItems
			if class of (item thisItem) is folder then my splitFolder(thisItem)
		end repeat
	end tell
end open

on splitFolder(sourceFolder)
	set allocBlocks to 4096 -- assume multiples of 4K
	set psLimit to 149248 * allocBlocks -- sort out your CD/DVD capacity here
	
	-- On systems prior to Tiger, an external sort routine's required.
	-- This one's at <http://scriptbuilders.net/category?id=1910>
	-- I keep it in a folder called "Libraries" in my Scripts folder.
	set sortF to (load script file ((path to scripts folder as Unicode text) & "Libraries:FinderSort().scpt"))
	
	tell application "Finder"
		-- Make a new folder on the desktop to hold the smaller, numbered folders.
		set sourceFolder to folder sourceFolder
		set splitFolder to (make new folder at desktop with properties {name:"Split of " & (name of sourceFolder)})
		
		-- Sort the files by modification date (youngest -> oldest).
		set Fref to a reference to every file of sourceFolder
		tell sortF to set sortedFiles to its FinderSort(Fref, "modification date")
		
		-- Start the folder numbers at 1001. (Only the last three digits used.)
		set folderNumber to 1001
		-- Go through the file list (oldest -> youngest), calculating
		-- their cumulative 'physical size' on the other medium.
		set cumulativePS to 0
		set j to (count sortedFiles)
		repeat with i from j to 1 by -1
			set thisFile to item i of sortedFiles
			set thisSize to thisFile's size
			repeat while (thisSize is missing value)
				set thisSize to thisFile's size
			end repeat
			set thisPS to my quantiseUp(thisSize, allocBlocks)
			set cumulativePS to cumulativePS + thisPS
			
			-- If the 'physical size' limit's reached... 
			if (cumulativePS is greater than or equal to psLimit) then
				-- If the current file's not too big to go onto another disk, move the rest of what
				-- we've got so far to a new, numbered folder, and include this file in the next round.
				if (thisPS < psLimit) then
					my moveFiles(sortedFiles, i + 1, j, folderNumber, splitFolder)
					set folderNumber to folderNumber + 1
					set cumulativePS to thisPS
					set j to i
				else -- If the current file's too big in its own right, skip it.
					beep
					tell application (path to frontmost application as Unicode text)
						display dialog "The file " & (name of item i of sortedFiles) & " is too big and has been left in the original folder." buttons {"OK"} default button 1 with icon caution giving up after 8
					end tell
					if (i = 1) then
						set sortedFiles to rest of sortedFiles
					else if (i = j) then
						set sortedFiles to items 1 thru (i - 1) of sortedFiles
					else
						set sortedFiles to items 1 thru (i - 1) of sortedFiles & items (i + 1) thru j of sortedFiles
					end if
					set cumulativePS to cumulativePS - thisPS
					set j to j - 1
				end if
			end if
		end repeat
		-- At the end, move any remaining files to a new, numbered folder.
		if (j > 0) then my moveFiles(sortedFiles, 1, j, folderNumber, splitFolder)
	end tell
	
	beep 2
	tell application (path to frontmost application as Unicode text)
		display dialog "Done!" buttons {"OK"} default button 1 with icon note
	end tell
end splitFolder

(* Create a numbered folder and move the relevant files to it. *)
on moveFiles(sortedFiles, i, j, folderNumber, splitFolder)
	tell application "Finder"
		set newFolder to (make new folder at splitFolder with properties {name:text 2 thru 4 of (folderNumber as Unicode text)})
		move items i thru j of sortedFiles to newFolder
	end tell
end moveFiles

(* Round up to nearest multiple of q *)
-- From aRounderRound, <http://scriptbuilders.net/category.php?id=445>
on quantiseUp(n, q)
	if q < 0 then set q to -q
	tell n div q * q
		if it < n then return it + q
		it
	end tell
end quantiseUp

This is just what I have been looking for, a script to break up folders for archiving. I am an absolute novice with applescript but have managed to change the sort to name rather than mod date but I want the files to be listed alphabetically in the new folders rather than the say for example a list of 1000 files with 500 in each are being labelled in 001 folder 501-1000 and 002 folder 1-500. How would I change the code so that 1-500 were in the first folder 001 and 501-1000 in the 002 folder.

Browser: Safari 312
Operating System: Mac OS X (10.3.9)

I have another query too. As I shoot RAW files and use another program to modify the .raf files which then gives me either a .rag file or an .xmp file. I would need the 2 or 3 files kept together rather than all the .raf then all the .rag and finally .xmp files when they are moved. Is it also possible for folders within a folder be moved as a complete folder too.

Browser: Safari 312
Operating System: Mac OS X (10.3.9)