Moves Files from all Subfolders to Main Folder Script


This did the trick:

I have a good script that moves files from subfolders in a main folder to the main folder–>

set main_folder to (choose folder with prompt "Choose the main folder")
tell application "Finder"
	set sub_folders to folders of main_folder
	repeat with each_folder in sub_folders
		move every file of each_folder to main_folder with replacing
	end repeat
end tell

How could this be modified to move files from every subfolder in the main folder? I need files in subfolders of subfolders to make the move too.


You may try this quick and dirty code :

# Define the main folder
set folderTarget to (path to desktop folder as text) & "folder:" as alias

script o
	property allPaths : missing value
end script

-- Get the paths to all the files in the chosen hierarchy.
tell application "Finder" to set allPaths of o to (files of entire contents of folderTarget as alias list)
repeat with anItem in o's allPaths
	--if anItem as text does not end with ":.DS_Store" then
		# Try useful if the main folder already contains files
		do shell script "mv " & quoted form of POSIX path of anItem & space & quoted form of POSIX path of folderTarget
	end try
	--end if
end repeat

I wrote “and dirty” because relying upon a try/end try block to skip the files already existing in the main folder is not what I call “a clean code”.
The disabled instructions filtering the .DS_Store files were useful on my machine where hidden files are unhidden.
As I added the try/end try to treat the possible files already available in the main folder, we may also rely upon it for the .DS_Store files.

Users visiting this forum regularly will recognize the structure of a script posted some days ago by Nigel Garvey.

Yvan KOENIG (VALLAURIS, France) vendredi 12 décembre 2014 22:08:32


probably not the fastest solution, the script walks recursively through the folder hierarchy

property main_folder : missing value

set main_folder to (choose folder with prompt "Choose the main folder")
tell application "Finder" to set mainFolderHasSubFolders to (count folders of main_folder) > 0
if mainFolderHasSubFolders then processFolders(main_folder)

on processFolders(_folder)
	tell application "Finder"
		set sub_folders to folders of _folder
		if (count sub_folders) > 0 then
			repeat with aSubFolder in sub_folders
			end repeat
			move every file of _folder to main_folder with replacing
		end if
	end tell
end processFolders

PS: faster solution

set main_folder to quoted form of POSIX path of (choose folder with prompt "Choose the main folder")
do shell script "/usr/bin/find " & main_folder & " -type f ! -name '.*'  -mindepth 2 -print -exec /bin/mv {} " & main_folder & " \\;"

So I made a folder, and made a subfolder within it. I put several files in it – half-a-dozen script library files and apps, as it happened. I then ran the “faster” script, choosing the folder.

Result: the script libraries and apps are destroyed because all the files in their bundles have been moved to the top folder, and in several cases have overwritten each other so the destruction is permanent. And the broken shells remain in the subfolder.

I’ll venture my opinion again: using find with -type f on Macs is simply asking for trouble.

This community is awesome. Thank you all for the help!

Of course you’re right.
A fast alternative is mdfind with query kMDItemContentTypeTree != public.folder.
But unlike /usr/bin/find there is no option to specify the hierarchy depth respectively to exclude the base folder

Assuming Mavericks or Yosemite, this will probably be hard to beat:

use AppleScript version "2.3.1"
use scripting additions
use framework "Foundation"

-- pick the folder
set thePath to POSIX path of (choose folder)
-- make an NSURL from it
set anNSURL to current application's |NSURL|'s fileURLWithPath:thePath
-- get the file manager
set theNSFileManager to current application's NSFileManager's defaultManager()
-- set options for the search
set theOptions to (current application's NSDirectoryEnumerationSkipsHiddenFiles as integer) + (current application's NSDirectoryEnumerationSkipsPackageDescendants as integer)
-- enumerate the folder
set theEnumerator to theNSFileManager's enumeratorAtURL:anNSURL includingPropertiesForKeys:{current application's NSURLIsDirectoryKey, current application's NSURLIsPackageKey} options:theOptions errorHandler:(missing value)
-- loop through the results
	set theNSURL to theEnumerator's nextObject()
	if theNSURL is missing value then exit repeat -- no more left
	-- see if it's a package and/or directory
	set theValues to theNSURL's resourceValuesForKeys:{current application's NSURLIsDirectoryKey, current application's NSURLIsPackageKey} |error|:(missing value)
	if (theValues's objectForKey:(current application's NSURLIsPackageKey)) as boolean or not (theValues's objectForKey:(current application's NSURLIsDirectoryKey)) as boolean then
		-- either a package or not a directory, so move it;
		-- get name of file, and add it to folder URL to get new URL
		set theNewURL to anNSURL's URLByAppendingPathComponent:(theNSURL's lastPathComponent())
		-- move it
		theNSFileManager's moveItemAtURL:theNSURL toURL:theNewURL |error|:(missing value)
	end if
end repeat