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.
# 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
# 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.
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
processFolders(aSubFolder)
end repeat
else
move every file of _folder to main_folder with replacing
end if
end tell
end processFolders
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.
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
repeat
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