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
Related
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
Please help, I can't think of a fix for this.
A folder action is meant to do this for each file copied into a folder:
Derive a subfolder name, and a new filename.
Create subfolder.
Move file into it.
Rename subfolder and file.
Files are copied from a different volume and are usually 500…1500 MB.
Problem: The moving step (step 3) in the folder action script fails if the files are that large and their number is >1
and they are copied from a different volume.
The script works fine when copying: small files, or from the same volume, or only one file.
In a test, all of 200 Alias' were correctly processed, but only 23 of 512. This is not a problem, the number of added_items is usually <10 and unlikely to ever be >50. But it may help targeting the issue.
I suspected a timing issue, but all attempts to fix it using generous timeout's didn't work.
The script (note - before trying, set the regex in the do shell script lines to something workable):
on adding folder items to this_folder after receiving added_items
repeat with the_item in added_items
with timeout of 3600 seconds
tell application "Finder"
if kind of the_item is not "Folder" then
repeat -- wait until item is copied. Thanks to original coder on the WWW.
set {size:fileSize, busy status:Busy} to (info for (the_item))
if not Busy and (fileSize is greater than 0) then exit repeat
delay 1
end repeat
with timeout of 600 seconds
set new_folder_name to do shell script "echo '" & (name of the_item) ¬
& "' | sed -E 's/llooongRegex/replace/g'"
set new_item_name to do shell script "echo '" & (name of the_item) ¬
& "' | sed -E 's/otherRegex/replace/g'"
set new_folder to (make new folder at this_folder with properties {name:(new_folder_name & "-temp")}) as alias -- "-temp" in case new folder and file will have the same name
move file the_item to folder new_folder -- <== fails if ((added_items >1) AND (files big, tested with 0.5…1.5GB) AND (copied from different volume)) ==> Timing issue?
set name of (first item of (get contents of new_folder)) to new_item_name
set name of new_folder to new_folder_name
end timeout
end if
end tell
end timeout
end repeat
end adding folder items to
P.S.: is folder-action frequent enough for a tag?
After replacing the repeat -- wait until item is copied.... clause with a simple delay 60, the script works. So it is a timing problem.
Waiting for the target folder to stop changing size as describe here works as long as only 1 file copying (bunch of files dropped) is running. Two or more drag'n drops, and it hiccups again (nice word, #vadian!).
Ditto when checking for the size of individual added items to remain constant.
I have all these movies in .dvdmedia format and I want to covert them all to a smaller file size such as .mp4.
But what I need to do is create an applescript that will copy the individual file to a folder 'Conversion'. Once the file in the folder is deleted it copies the next item and deletes the previous.
I've completed an Automation script that once the item is added to the folder is starts formatting the file through TurboHD then deletes the file and moves the converted item to another folder 'Completed'
Does anyone able to help me with this?
Please note that the location of the movies are on a NAS drive
there :) I coded the following. Please note to save it as an Application with Stay open after run handler checked.
You have to set the source and the target path to the paths in your environment.
Finally you have to set the return value. The value sets the interval in seconds to wait until next execution. If each of your conversions takes about an hour, I think I would check every 5 minutes meaning the handler has to return 300.
-- The idle-Handler defines a repetitive task
-- Note: Save as Application with option "Stay open after run handler"
on idle
-- define the folders to watch
set theSourceFolder to (POSIX file "/Users/myHomeFolder/Desktop/Conversion_Source") as alias
set theTargetFolder to (POSIX file "/Volumes/myMountedVolume/Conversion") as alias
-- check the contained files (get visible files only because of .DS_Store etc.)
tell application "System Events"
set availableSourceFiles to every file of theSourceFolder whose visible is true
set filesOfTargetFolder to files of theTargetFolder whose visible is true
end tell
-- if no more source file is available, quit this script
if (count of availableSourceFiles) = 0 then
quit
end if
-- if the target folder is empty start move
if (count of filesOfTargetFolder) = 0 then
-- get the first item from source folder
set sourceFile to (first item of availableSourceFiles) as alias
-- use the Finder to copy the file
tell application "Finder"
-- duplicate the file to the target folder
duplicate sourceFile to theTargetFolder
-- move the source file to trash after copy
move sourceFile to trash
end tell
end if
-- the integer returned is the time to wait (in seconds)
-- here: two minutes
return 120
end idle
Enjoy, Michael / Hamburg
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
I've been searching a lot for a script like this but I can't find it. I suspect it's similar to this
but not exactly, and I'm not sure how to modify it to work for me.
I have a group of files with multiple names like this....
File Name Vyear #01 (year).ext
FileName Vyear #01 (year).ext
and so forth, the convention is always the same.
Filename (sometimes multiple words) followed by V for Version then the year in parenthesis then followed by a number then another year in parenthesis. It's complicated but it's all there for a reason. What I'm looking for is a way to automate moving all those files into subfolders based on only the first part of that name. So that a file like this...
The Mist V2000 #01 (2011).zip
Would get moved to a folder named this.
The Mist V2000
I'm constantly having to make files like this and I'd love to get them sorted into sub-folders. My problem is that I'm not sure how to select just the first of the name (an account for files that have two or three words in the title) and the volume number only to create the subfolder and then match the filenames for the move.
I hope I'm explaining this properly. If anyone could help I would appreciate it.
Cheers.
Try this. Basically we can calculate the folder name if we know where the "#" character is in the file name. Then we can get all of the text up to there - 2 characters. Then you just have to make that folder and move the file into it. Simple. Good luck.
set sourceFolder to choose folder
tell application "Finder"
set theFiles to files of sourceFolder
repeat with aFile in theFiles
set fileName to name of aFile
if fileName contains "#" then
set poundOffset to offset of "#" in fileName
set folderName to text 1 thru (poundOffset - 2) of fileName
set newFolder to (sourceFolder as text) & folderName & ":"
if not (exists folder newFolder) then
make new folder at sourceFolder with properties {name:folderName}
end if
move aFile to folder newFolder
end if
end repeat
end tell