AppleScript - Move all the files contained in subfolder to a top folder - applescript

I am looking for an edit to the current script. What I need is moving all the files from subfolders (recursively) in to one top folder, however if a file with the same name exist, create a new top-folder and continue there, this is what I have so far:
tell application "Finder"
try
set Random_name to random number from 100 to 9999
set theTopFolder to (choose folder)
set theFiles to a reference to every file of (entire contents of folder theTopFolder)
set theNewFolder to make new folder at theTopFolder with properties {name:"Flattened Files"}
move theFiles to theNewFolder
on error
set theNewFolder to make new folder at theTopFolder with properties {name:"Flattened Files" & Random_name}
move theFiles to theNewFolder
end try
end tell
Just to be clear the structure of the path is not:
Mainfolder/subfolder/file.xxx but Mainfolder/subfolder/sulbfolder2/subfolder3/....100/file.xxx so the script needs to work recursively which it does but it stops when a file exist with the same name
When a file with the same name exist my edit creates a new folder with Flattened Files+random number however when another file with the same name is moved the script stops for an error instead going ahead and creating a new Flattened Files+randonnumber folder. Any ideas?
Thank you

Your script isn't using recursion, it just lets the Finder get all the files. The additional error you are getting is because you are trying to move the whole list of files again.
One solution would be to step through the file items, testing for duplicates as you go, and make new folders as needed. The following script just moves duplicates to added folders (note that an error will still stop the script). I don't know how you are sorting the file list, so I included a line to uncomment to continue moving file items to the added folder.
set theTopFolder to (choose folder)
tell application "Finder"
set theNewFolder to make new folder at theTopFolder with properties {name:"Flattened Files"}
set theFiles to every file of (entire contents of folder theTopFolder) as alias list
repeat with aFile in theFiles
if file ((theNewFolder as text) & (name of aFile)) exists then -- use added folders for duplicates
set counter to 1
set done to false
repeat until done
set suffix to text -2 thru -1 of ("000000" & counter) -- leading zeros for sorting
set alternateFolder to (theTopFolder as text) & "Flattened Files" & space & suffix
tell me to (do shell script "mkdir -p " & quoted form of POSIX path of alternateFolder) -- make new folder as needed
if file (alternateFolder & ":" & (name of aFile)) exists then -- continue to next one
set counter to counter + 1
else
move aFile to folder alternateFolder
# set theNewFolder to folder alternateFolder -- uncomment to continue moving here after a duplicate
set done to true
end if
end repeat
else
move aFile to folder (theNewFolder as text)
end if
end repeat
end tell

Related

AppleScript / FolderAction - Rename files when dropped in folder > Endless Loop

I am trying to do the following with a FolderAction and AppleScript:
Everytime I drop a file on a specific folder it should be renamed and then moved into another folder.
The problem is I get something like an infinite loop (I think) because when the file gets renamed the folder assumes that there is a new file in the folder and so on.
I really don't know how to avoid this and stop the endless loop. Here ist my script:
global newName
set newName to ""
on adding folder items to theAttachedFolder after receiving theNewItems
-- Get the name of the attached folder
tell application "Finder"
set theName to name of theAttachedFolder
-- Count the new items
set theCount to length of theNewItems
-- Display an alert indicating that the new items were received
activate
-- Loop through the newly detected items
repeat with anItem in theNewItems
set oldFileName to name of anItem
-- Rename the file
set the name of anItem to "NewFile" & oldFileName
-- Move the file to other folder
move anItem to "Macintosh HD:Users:blabla:blabla"
end repeat
end tell
tell application "Finder"
delete files of folder "Macintosh HD:Users:user:thisfolder
end tell
end adding folder items to
You are right, renaming the file triggers the folder action again.
The solution is to change the order: First move then rename.
-- Move the file to other folder
set movedItem to move anItem to "Macintosh HD:Users:blabla:blabla"
-- Rename the file
set the name of movedItem to "NewFile" & oldFileName

AppleScript : How to get files in folder without hidden files?

I actually have two questions.
How to exclude hidden files like .DS_STORE, Icon when I try to get files in folder ?
I've tried "without invisibles" but it seems not working.
How to set my var the_new_folder as an existing folder if already exists ?
Thanks for answers.
My code:
--
-- Get all files in a selected folder
-- For each file, create a folder with the same name and put the file in
--
tell application "Finder"
set the_path to choose folder with prompt "Choose your folder..."
my file_to_folder(the_path)
end tell
on file_to_folder(the_folder)
tell application "Finder"
-- HELP NEEDED HERE
-- HOW TO EXCLUDE HIDDEN FILES (Like Icon, .DS_STORE, etc)
set the_files to files of the_folder
repeat with the_file in the_files
-- Exclude folder in selection
if kind of the_file is not "Folder" then
set the_path to container of the_file
set the_file_ext to name extension of the_file
-- Remove extension of the file name
set the_file_name to name of the_file as string
set the_file_name to text 1 thru ((offset of the_file_ext in (the_file_name)) - 2) of the_file_name
-- Make the new folder with the file name
try
set the_new_folder to make new folder at the_path with properties {name:the_file_name}
on error
-- HELP NEEDED HERE
-- HOW TO SET the_new_folder AS THE EXISTING FOLDER
end try
-- Move the file in the new folder
move the_file to the_new_folder
end if
end repeat
end tell
end file_to_folder
tell application "Finder"
(display dialog ("It's done!") buttons {"Perfect!"})
end tell
Using the System Events context instead of Finder:
bypasses the problem with the AppleShowAllFiles preference[1]
is much faster in general.
Using the visible property of file / folder objects in the System Events context allows you to predictably determine either all items, including hidden ones (by default), or only the visible ones (with whose visible is true):
# Sample input path.
set the_path to POSIX path of (path to home folder)
tell application "System Events"
set allVisibleFiles to files of folder the_path whose visible is true
end tell
Simply omit whose visible is true to include hidden files too.
The code for either referencing a preexisting folder or creating it on demand is essentially the same as in the Finder context:
# Sample input path.
set the_path to POSIX path of (path to home folder)
# Sample subfolder name
set the_subfolder_name to "subfolder"
tell application "System Events"
if folder (the_path & the_subfolder_name) exists then
set subfolder to folder (the_path & the_subfolder_name)
else
set subfolder to make new folder at folder the_path ¬
with properties {name: the_subfolder_name}
end if
end tell
[1] In order to predictably exclude hidden items, a Finder-based solution is not only cumbersome but has massive side effects:
You need to determine the current state of the the AppleShowAllFiles preference (defaults read com.apple.Finder AppleShowAllFiles),
then turn it off.
then kill Finder to make the change take effect (it restarts automatically) - this will be visually disruptive
then, after your code has run, restore it to its previous value.
then kill Finder again so that the restored value takes effect again.
I believe that your first question is not a problem. Your code works fine for me.
As for the second issue, the simplest method is to use the text representation of the_path, and simply build the new folder, and see if it already exists:
set the_path_Text to (the_path as text)
set try_Path to the_path_Text & the_file_name
if (folder try_Path) exists then
set the_new_folder to (folder try_Path)
else
set the_new_folder to make new folder at the_path with properties {name:the_file_name}
end if
If you are truly having difficulty with the first code section, please post a new question with more details, such as a copy of the Result section of the Script.
Thank you to all of you ! #mklement0 #craig-smith
You will find below the corrected code with your help!
If I share this code, you want to be cited for thanks?
--
-- Get all files in a selected folder
-- For each file, create a folder with the same name and put the file in
--
-- Get user folder
set the_path to choose folder with prompt "Choose your folder..."
my file_to_folder(the_path)
on file_to_folder(the_folder)
tell application "System Events"
-- Get all files without hidden
set the_files to files of the_folder whose visible is true
repeat with the_file in the_files
-- Remove extension of the file name
set the_file_ext to name extension of the_file
set the_file_name to name of the_file as string
set the_file_name to text 1 thru ((offset of the_file_ext in (the_file_name)) - 2) of the_file_name
-- Make a new folder or get the existing
set the_path to POSIX path of the_folder
if folder (the_path & the_file_name) exists then
set the_new_folder to folder (the_path & the_file_name)
else
set the_new_folder to make new folder at folder the_path with properties {name:the_file_name}
end if
-- Move the file to the new folder
move the_file to the_new_folder
end repeat
end tell
end file_to_folder
-- Ending dialog
display dialog ("It's done!") buttons {"Perfect!"}

Trouble with script moving files to a newly created folder in Applescript

I am having trouble with what I think is a pretty straightforward task, but cannot seem to get my script to work correctly. I have found a lot of help through the forums with regards to the individual routines used, but it still seems to fail.
In short, what I would like to do is monitor a folder for new files being added. Once a batch of files are added (every other day or so), it will create a folder in another directory with the new folder name being the current date, move those files to the new directory, and then execute a simple bash script which uses the new directory name as an argument.
My script compiles ok, but once files are added it only creates the new folder and nothing else. I appreciate any help.
property the_sep : "-"
on adding folder items to my_folder after receiving the_files
tell application "Finder"
(* First create a new folder with name of folder = current date *)
set the_path to (folder "qa" of folder "Documents" of folder "ehmlab" of folder "Users" of disk "Macintosh HD")
set the_name to (item 1 of my myDate())
set the_name to (the_name & the_sep & item 2 of my myDate())
set the_name to (the_name & the_sep & item 3 of my myDate())
make folder at the_path with properties {name:the_name}
set newDir to the_path & the_name
end tell
(* Next, move the newly added files to the source into the newly created date folder *)
repeat with i from 1 to number of items in the_files
tell application "Finder"
try
set this_file to (item i of the_files)
move file this_file to folder newDir
end try
end tell
end repeat
do shell script "qc.sh " & newDir
end adding folder items to
on myDate()
set myYear to "" & year of (current date)
set myMth to text -2 thru -1 of ("0" & (month of (current date)) * 1)
set myDay to text -2 thru -1 of ("0" & day of (current date))
return {myYear, myMth, myDay}
end myDate
The failure reason are different path styles.
AppleScript uses HFS paths (colon separated).
UNIX uses POSIX paths (slash separated).
The solution is to coerce the HFS path string to POSIX path
do shell script "qc.sh " & quoted form of POSIX path of newDir
This is a shorter version of the script using the shell also for the time stamp and for creating the directory.
on adding folder items to my_folder after receiving the_files
(* Next, move the newly added files to the source into the newly created date folder,
"path to documents" is a relative path to the documents folder of the current user *)
set baseFolder to (path to documents folder as text) & "qa:"
set timeStamp to do shell script "date +%Y-%m-%d"
set newDir to baseFolder & timeStamp
do shell script "mkdir -p " & quoted form of POSIX path of newDir
(* Next, move the newly added files to the source into the newly created date folder *)
repeat with aFile in the_files
tell application "Finder"
try
move aFile to folder newDir
end try
end tell
end repeat
do shell script "qc.sh " & quoted form of POSIX path of newDir
end adding folder items to

AppleScript: Move contents of folder in user defined amount to folders?

I'm fairly new at this and while having managed to created several basic scripts over the last few weeks I cannot seem to wrap my head around this one:
Choose Folder (with say 1000 Files)
Enter the number of Files per Folder (say 100)
The script then creates 10 Folders (1000 Files / 100 in each folder)
The script then moves the first 100 files sequentially into the the first folder - repeats till done.
The scripts I've put together for this process to this point are dismal, sloppy and outright pathetic so I dare not share them here.
My experiments have also resulted in the item listing causing issues with moving the files sequentially.
instead of:
ValOne_1.wav
ValOne_2.wav
ValOne_3.wav
ValOne_4.wav
ValOne_5.wav
I get:
ValOne_1.wav
ValOne_10.wav
ValOne_100.wav
ValOne_101.wav
ValOne_102.wav
Thanks
The Finder has a "sort" command so you can use that to avoid the numbering problem you mention. It seems to sort them the way you expect. So using that your workflow becomes easy with a little clever coding. Try the following. You only need to adjust the first 2 variables in the script to suit your needs and the rest of the script should just work.
set filesPerFolder to 3
set newFolderBaseName to "StorageFolder_"
set chosenFolder to (choose folder) as text
tell application "Finder"
-- get the files from the chosen folder and sort them properly
set theFiles to files of folder chosenFolder
set sortedFilesList to sort theFiles by name
set theCounter to 1
repeat
-- calculate the list of files to move
-- also remove those files from the sortedFilesList
if (count of sortedFilesList) is greater than filesPerFolder then
set moveList to items 1 thru filesPerFolder of sortedFilesList
set sortedFilesList to items (filesPerFolder + 1) thru end of sortedFilesList
else
set moveList to sortedFilesList
set sortedFilesList to {}
end if
-- calculate the new folder information and make it
set newFolderName to newFolderBaseName & theCounter as text
set newFolderPath to chosenFolder & newFolderName
if not (exists folder newFolderPath) then
make new folder at folder chosenFolder with properties {name:newFolderName}
end if
-- move the moveList files
move moveList to folder newFolderPath
if sortedFilesList is {} then exit repeat
set theCounter to theCounter + 1
end repeat
end tell

Applescript - move files to folder which name begins with first 7 characters of filename

I've got 2 folders
the first folder contains all the files which I'd like to move to a subfolder of the second folder. I'd like to this based on the first 7 characters of both the file & folder names.
So if the first 7 characters of the subfolder in FOLDER 2 matches the first 7 characters of the file in FOLDER 1. The file get's moved into the subfolder of FOLDER 2
Right now I've got an Applescript which works, but it's terribly slow.
Here's the script so far:
set mgFileList to ""
set mgDestFolder to ""
set mgFilesFolder to (choose folder with prompt "Where are the files stored which you would like to move to the destination?")
set mgDestFolder to (choose folder with prompt "Where is the destination folder?")
set folderList to contents of mgDestFolder
tell application "Finder" to set fileList to files of mgFilesFolder
repeat with aFile in fileList
set prefix to getPrefix(name of aFile)
tell application "Finder"
try
set destinationFolder to (1st folder of mgDestFolder whose name begins with prefix)
move aFile to destinationFolder
end try
end tell
end repeat
on getPrefix(aName)
set prefix to text 1 thru 7 of aName
return prefix
end getPrefix
I've only recently got into Applescripting. Can this be done more efficiently within Applescript? I've searched around for a solution which works with a shell script (which I think will probably be a lot faster), but haven't been able to get any of them working.
I'm working on OSX Mountain Lion 10.8.4
--
edit
I see that I've uploaded the wrong version of the script I've managed to put together so far. Above is the script that is working, but it's really slow. Probably because it doesn't use any shell script.
---------------update-------------------
Here is the final script that is working pretty fast right now:
set mgFilesFolder to choose folder with prompt "Where are the files stored which you would like to move to the destination?"
set mgDestFolder to choose folder with prompt "Where is the destination folder?"
tell application "System Events"
set fileList to files of mgFilesFolder whose name does not start with "."
repeat with aFile in fileList
set prefix to my getPrefix(name of aFile)
try
set destinationFolder to (1st folder of mgDestFolder whose name begins with prefix)
move aFile to POSIX path of destinationFolder
end try
end repeat
end tell
on getPrefix(aName)
try
set prefix to text 1 thru 7 of aName
return prefix
on error
return aName
end try
end getPrefix
The Finder is generally a slow program because it does a lot of things on your computer. Therefore you should avoid using it if possible. In your case these tasks can be done using System Events. Try this, maybe it will be faster. Note that you had a couple mistakes in your code which are fixed in this code.
set mgFilesFolder to choose folder with prompt "Where are the files stored which you would like to move to the destination?"
set mgDestFolder to choose folder with prompt "Where is the destination folder?"
tell application "System Events"
set fileList to files of mgFilesFolder whose name does not start with "."
repeat with aFile in fileList
set prefix to my getPrefix(name of aFile)
try
set destinationFolder to (1st folder of mgDestFolder whose name begins with prefix)
move aFile to POSIX path of destinationFolder
end try
end repeat
end tell
on getPrefix(aName)
try
set prefix to text 1 thru 7 of aName
return prefix
on error
return aName
end try
end getPrefix
Not sure how many files you're working with, but I tested this with 10 folders and ~100 files, and it took less than 4 seconds to run. Working with strings is much faster than working with files, so the script gets the files/folders as strings and builds aliases when they're needed.
set mgFilesFolder to (choose folder with prompt "Where are the files stored which you would like to move to the destination?")
set mgDestFolder to (choose folder with prompt "Where is the destination folder?")
--Always use System Events whenever possible. It's WAY faster than Finder.
tell application "System Events"
set folderList to name of folders of mgDestFolder
set fileList to name of files of mgFilesFolder
end tell
repeat with i from 1 to (count folderList)
set folderName to item i of folderList
set filesToMove to {}
repeat with j from 1 to (count fileList)
set filename to item j of fileList
if filename begins with folderName then
set end of filesToMove to alias ((mgFilesFolder as string) & filename)
end if
end repeat
--Can't use system events for moving files. You have to use Finder.
tell application "Finder"
move filesToMove to alias ((mgDestFolder as string) & folderName & ":")
end tell
end repeat
It might be easier to use shell scripting:
cd FOLDER1; for f in *; do d=../FOLDER2/"${f:0:7}"*; [[ -d $d ]] && mv "$f" "$d"; done

Resources