Sorry if it has already discussed but I'm unable to find an answer.
I would like to add files from a choosen folder to an existing iTunes' playlist.
I don't want to copy/duplicate these files (so iTunes would create a new folder inside its Music folder).
If I use:
add myFolder to playlist playListName
songs are duplicated in a new "Music" folder
If I use:
add myFile to playlist playListName
I have a type error, something about «class cUsP» id 20647 of «class cSrc» id 66 of application "iTunes".
My app code contains several subroutines, not easy to understand unless I post the entire code.
myFolder can be defined by dropping a folder onto the app, or by command choose folder.
Then, playListName is extracted from the choosen folder's pathname.
Then, folder is processed like this, in order to create playlist:
on processFolder(thisFolder, playListName)
tell application "iTunes"
activate
-------------------------------- create playlist
try
set newPlaylist to (make new user playlist with properties {name:playListName})
set view of browser window 1 to newPlaylist
on error errMsg
beep
my dlog("Unable to create playlist " & my kwote(playListName) & "." & return & return & errMsg, {"Abort"}, appTitle, "error")
return false
end try
--***add thisFolder to newPlaylist -- create new "Music folder" and duplicate files !!!
--------------- add files --> tracks
tell application "Finder"
repeat with thisFile in (get every file of folder thisFolder)
if (my isValidFile(thisFile)) then
tell application "iTunes"
try
add thisFile to playlist playListName -- ERROR !!!
on error errMsg
beep
my dlog("Unable to add file " & my kwote(thisFile as text) & "." & return & return & errMsg, {"Abort"}, appTitle, "error")
return false
end try
end tell
end if
end repeat
end tell
return true
end tell
end processFolder
on isValidFile(thisFile)
tell application "Finder"
set the fileInfo to (info for thisFile as alias)
if (mp3Check) then
if (alias of the fileInfo is false) and ((the file type of the fileInfo is in the typesList) or (the name extension of the fileInfo is in the extensionsList)) then return true
else
if (alias of the fileInfo is false) then return true
end if
return false
end tell
end isValidFile
Thank you.
Related
Thanks everyone for your help so far. And apologies I asked this in the 'answer' section of a previous question which I now understand I shouldn't have done ..... so I have started a new question here.
SO, I wanted to write a script to save the attachments in emails as they arrive - with a different folder for each email sender. I got a lot of help from people on this site.
It sort of works ..... for new incoming emails it works perfectly, but when I run it against my old emails in my mailbox it saves some attachments and not others.
I thought the problem was an error on finding a duplicate (which I thought would be unlikely as I have added the time stamp to the filename along with the data stamp of the email.) So I added the delFile delete process to check for a file of the same name and if it finds it to delete it.
When I execute the script it processes a few more attachments than before but not all by any means..... and interestingly nothing get put in the trash bin.
I am now stumped!! As a newcomer to AppleScript I don't know how to debug or handle errors yet.
Can anyone help please?
use scripting additions
using terms from application "Mail"
on perform mail action with messages messageList for rule aRule
set destinationPath to (POSIX file "/volumes/Data/Dropbox/WORK ITEMS/Email Attachments/") as string
tell application "Mail"
repeat with aMessage in messageList
repeat with anAttachment in mail attachments of aMessage
set senderName to (extract name from sender of aMessage)
set {year:y, month:m, day:d, hours:h, minutes:min} to date received of aMessage
set timeStamp to (d & "/" & (m as integer) & "/" & y & " " & h & "." & min) as string
set attachmentName to timeStamp & " - " & name of anAttachment
set doSave to true
set originalName to name of anAttachment
if originalName contains "jpg" then
set doSave to false
else if originalName contains "jpeg" then
set doSave to false
else if originalName contains "gif" then
set doSave to false
else if originalName contains "png" then
set doSave to false
else if originalName contains "html" then
set doSave to false
else if originalName contains "ics" then
set doSave to false
end if
if doSave is true then
tell application "System Events"
if not (exists folder (destinationPath & senderName)) then
make new folder at end of alias destinationPath with properties {name:senderName}
end if
end tell
end if
if doSave is true then
set delFile to destinationPath & senderName & ":" & attachmentName
tell application "System Events" to if (exists file delFile) then delete file delFile
end if
if doSave is true then save anAttachment in file (destinationPath & senderName & ":" & attachmentName) with replacing
end repeat
end repeat
end tell
end perform mail action with messages
end using terms from
Thanks
I'm not sure I can help with the precise reason for your script's failure, but I might be able to help you see where it's failing.
First of all, I would substitute a list of file extensions that you wish to exclude for the long if...else if block. Something like:
set ignore list to {".jpg", ".jpeg", ".gif", ".png", ".html", ".ics"} at the top of the script, with set fileExtension to rich text (offset of "." in originalName) thru end of originalName in the loop.
You can then test:
if fileExtension is not in ignoreList then
and wrap this around the saving code (you don't need to do the same test several times).
I think your delete file block is redundant, because it should be doing the same as the following save...with replacing (if the file's already there). (You may want to delete the file if it exists, in which case remove the with replacing later on.)
To start debugging, first of all remove the code up top that works with incoming messages and replace it with set messageList to selection. Try inserting some display dialog <varname> in places where you're not sure what's happening. For example, you know what anAttachment is but are you certain what destinationPath & senderName & ":" & attachmentName are?
Finally, note that I have NOT run this on YOUR data, so be sure to do a back-up. It shouldn't destroy anything, but better safe than sorry!
Please come back with any questions. Good luck!
EDIT:
I have added a function at the top (the on getExtension(fileName) block. This is called by the line set fileExtension to my getExtension(originalName)
This is to refine extension getting by reversing the name string, so that only the first '.' is found. Once got the extension is reversed.
Another crucial part is that this contains try ... on error ... end try. This is how AppleScript does error handling. If there is no '/' an error is thrown. This is caught by on error which returns 'skip'. (At this point this is not used in the main program, but could be used to funnel all the output to a catchall folder.)
The final change is that I have wrapped the saving part in If originalName does not contain "/" then ... end if. This is to catch those files that contain a '/' and to 'jump over' them without doing anything.
I have NOT needed to add a delay, so try without one to start with. It might have been a red herring!
set ignoreList to {".jpg", ".jpeg", ".gif", ".png", ".html", ".ics"}
set destinationPath to (POSIX file "/volumes/Data/Dropbox/WORK ITEMS/Email Attachments/") as string
on getExtension(fileName)
try
set fileName to (reverse of every character of fileName) as string
set extension to text 1 thru (offset of "." in fileName) of fileName
set extension to (reverse of every character of extension) as string
return extension
on error
return "skip"
end try
end getExtension
tell application "Mail"
set messageList to selection
repeat with aMessage in messageList
repeat with anAttachment in mail attachments of aMessage
set senderName to (extract name from sender of aMessage)
set {year:y, month:m, day:d, hours:h, minutes:min} to date received of aMessage
set timeStamp to (d & "/" & (m as integer) & "/" & y & " " & h & "." & min) as string
set attachmentName to timeStamp & " - " & name of anAttachment
set originalName to name of anAttachment
if originalName does not contain "/" then
set fileExtension to my getExtension(originalName)
if fileExtension is not in ignoreList then
tell application "System Events"
if not (exists folder (destinationPath & senderName)) then
make new folder at end of alias destinationPath with properties {name:senderName}
end if
end tell
save anAttachment in file (destinationPath & senderName & ":" & attachmentName) with replacing
end if
end if
end repeat
end repeat
end tell
For calling from a mail rule:
use scripting additions
set ignoreList to {".jpg", ".jpeg", ".gif", ".png", ".html", ".ics"}
set destinationPath to (POSIX file "/Users/bernardharte/test/") as string
on getExtension(fileName)
try
set fileName to (reverse of every character of fileName) as string
set extension to text 1 thru (offset of "." in fileName) of fileName
set extension to (reverse of every character of extension) as string
return extension
on error
return "skip"
end try
end getExtension
using terms from application "Mail"
on perform mail action with messages messageList for rule aRule
tell application "Mail"
repeat with aMessage in messageList
repeat with anAttachment in mail attachments of aMessage
set senderName to (extract name from sender of aMessage)
set {year:y, month:m, day:d, hours:h, minutes:min} to date received of aMessage
set timeStamp to (d & "/" & (m as integer) & "/" & y & " " & h & "." & min) as string
set attachmentName to timeStamp & " - " & name of anAttachment
set originalName to name of anAttachment
if originalName does not contain "/" then
set fileExtension to my getExtension(originalName)
if fileExtension is not in ignoreList then
tell application "System Events"
if not (exists folder (destinationPath & senderName)) then
make new folder at end of alias destinationPath with properties {name:senderName}
end if
end tell
save anAttachment in file (destinationPath & senderName & ":" & attachmentName) with replacing
end if
end if
end repeat
end repeat
end tell
end perform mail action with messages
end using terms from
I am writing an AppleScript to handle some MTS files. The script recursively iterates through the subfolders of the top-level folder "Volumes:G-Drive:video". The subfolders are arranged into year folders, starting with the folder named "2005" for the year 2005. The runtime error is occurring with the very first folder "2005" that the script tries to iterate. I suspected it is something to do with how I am handling aliases and text, but I am stumped at this point how to fix it. The error at runtime is this:
Can’t make {alias "G-DRIVE:video:", "2005:"} into type integer.
I don't know where in my code an integer type comes into play so as to get this error. Script Editor doesn't point me to the location of the runtime error in the code, so i don't know how to figure out which line is causing this either.
set folderName to "Volumes:G-Drive:video" as alias
my processFolder("", folderName)
on processFolder(root, folderNameToProcess)
tell application "Finder"
set theItems to every file of folder (root & folderNameToProcess)
repeat with theFile in theItems
set Nm to name of theFile as text
set Ex to name extension of theFile
if Nm does not contain "-c" and Ex is "MTS" then
set NmMinusExt to my remove_extension(Nm)
set logMsg to "Deleting " & Nm
my logThis(logMsg)
tell application "Finder" to delete theFile
end if
end repeat
set theItems to every file of folder (root & folderNameToProcess)
repeat with theFile in theItems
set Nm to name of theFile as text
set Ex to name extension of theFile
--tell (info for theFile) to set {Nm, Ex} to {name, name extension}
if Nm contains "-c" and Ex is "MTS" then
set NmMinusExt to my remove_extension(Nm)
set shortNm to my remove_lastTwoCharacters(NmMinusExt)
set name of theFile to shortNm & ".MTS" as text
set logMsg to "Renaming " & Nm
my logThis(logMsg)
--set lastTwoLetters to characters (((length of Nm) - 2) as number) thru (((length of Nm) - 0) as number) of (Nm as text)
--if lastTwoLetters is "-c" then
--display notification lastTwoLetters
--end if
end if
end repeat
set theFolders to name of folders of folder (root & folderNameToProcess)
repeat with theFolder in theFolders
copy theFolder as string to TheFolderName
display notification "found folder named: " & TheFolderName
set firstChar to (text 1 thru 1 of TheFolderName)
if firstChar is not "." then
--display dialog (folderNameToProcess & TheFolderName & ":")
try
my processFolder(folderNameToProcess, TheFolderName & ":")
on error errStr number errorNumber
display dialog errStr
end try
end if
end repeat
end tell
return
end processFolder
on remove_extension(this_name)
if this_name contains "." then
set this_name to ¬
(the reverse of every character of this_name) as string
set x to the offset of "." in this_name
set this_name to (text (x + 1) thru -1 of this_name)
set this_name to (the reverse of every character of this_name) as string
end if
return this_name
end remove_extension
on remove_lastTwoCharacters(this_name)
set this_name to ¬
(the reverse of every character of this_name) as string
set this_name to (text 3 thru -1 of this_name)
set this_name to (the reverse of every character of this_name) as string
return this_name
end remove_lastTwoCharacters
The Events pane of Script Editor produces the following trace:
tell application "Finder"
get every file of folder "G-DRIVE:video:"
get every file of folder "G-DRIVE:video:"
get name of every folder of folder "G-DRIVE:video:"
display notification "found folder named: 2005"
end tell
tell application "Script Editor"
display notification "found folder named: 2005"
end tell
tell application "Finder"
get every file of folder {alias "G-DRIVE:video:", "2005:"}
display dialog "Finder got an error: Can’t make {alias \"G-DRIVE:video:\", \"2005:\"} into type integer."
folderName is an alias. The attempt to concatenate an alias and a string creates a list which the error indicates.
The solution is to use only (HFS) string paths.
Replace
set folderName to "Volumes:G-Drive:video" as alias
with
set folderName to "G-Drive:video:"
The trailing colon is crucial to be able to add path components
I have found similar solutions like this:
property theOpenFile : missing value
tell application "Finder" to set theSel to selection
if theSel is not {} then
set pathToYourTextFile to (path to desktop folder as string) & "SampleTextFile2.txt"
set theOpenFile to open for access file (pathToYourTextFile as string) with write permission
repeat with aItem in theSel
tell application "Finder" to class of aItem is folder
if the result then my getFilesIn(aItem) -- aItem is a folder
end repeat
close access theOpenFile
end if
on getFilesIn(thisFolder)
tell application "Finder" to set theseFiles to files of thisFolder as alias list
repeat with thisFile in theseFiles
set f to thisFile as string
set pathLength to length of f
if pathLength > 255 then my writeToFile(f)
end repeat
tell application "Finder" to set theseSubFolders to folders of thisFolder
repeat with tSubF in theseSubFolders
my getFilesIn(tSubF) -- call this handler (recursively through this folder)
end repeat
end getFilesIn
on writeToFile(t)
write (t & return) to theOpenFile starting at eof
end writeToFile
They all work in with a file reference in alias format. As I understand I cannot change the filename of the original in this case, or delete it, etc. and thats what I want to do.
Am I right ? If yes what else can I do ?
You can rename and delete files, the Finder can handle alias specifiers
repeat with thisFile in (get theseFiles) -- you need get to capture the reference list
set f to thisFile as string
set pathLength to length of f
if pathLength > 255 then my writeToFile(f)
tell application "Finder" to set name of thisFile to "foo.txt"
-- or
tell application "Finder" to delete thisFile
end repeat
or rather than an alias you can use Finder file specifiers
repeat with thisFile in (get theseFiles)
set f to thisFile as string
set pathLength to length of f
if pathLength > 255 then my writeToFile(f)
tell application "Finder" to set name of file f to "foo.txt"
-- or
tell application "Finder" to delete file f
end repeat
I have baby photos in a folder and I want to upload them one at a time about every hour (4000 secs not 3600 secs) to a shared iCloud album that all my relatives see on their iPhones and iPads and macs. Here is my applescript saved as an application with the keep open box checked. I think it's not quite right. What's wrong?
on idle
set importFolder to "Amac:Users:AbuDavid:Downloads:uploadBABY"
set extensionsList to {"jpg", "png", "tiff"}
tell application "Finder" to set theFiles to some file of importFolder whose name extension is in extensionsList
if (count of theFiles) < 1 then
display dialog "No images selected!" buttons "OK"
else
set albumName to "BabyDouDou"
set timeNow to time string of (current date)
set today to date string of (current date)
set albumName to albumName & " " & timeNow & " " & today
set imageList to theFiles
tell application "Photos"
activate
delay 2
import imageList into albumName skip check duplicates yes
end tell
tell application "Finder" to move theFiles to trash
end if
return 4000
end idle
There are some issues:
The Finder needs the keyword folder – not just a literal string – to specify a folder.
some file returns always one file so the count command fails and returns always 0.
albumName is a literal string as well rather than a object specifier.
Photos.app expects alias specifiers for the files to be imported rather than Finder object specifiers.
Try this
on idle
set importFolder to (path to downloads folder as text) & "uploadBABY"
set extensionsList to {"jpg", "png", "tiff"}
tell application "Finder" to set theFiles to files of folder importFolder whose name extension is in extensionsList
if (count theFiles) < 1 then
display dialog "No images selected!" buttons "OK"
else
set theFile to some item of theFiles
set albumName to "BabyDouDou"
set timeNow to time string of (current date)
set today to date string of (current date)
set albumName to albumName & " " & timeNow & " " & today
set imageList to {theFile as alias}
tell application "Photos"
activate
delay 2
if not (exists container albumName) then
set theAlbum to make new album
set name of theAlbum to albumName
else
set theAlbum to container albumName
end if
import imageList into theAlbum skip check duplicates yes
end tell
tell application "Finder" to move theFiles to trash
end if
return 4000
end idle
Made a small change to only delete the image that was uploaded and not all the images. Thank you so much.
on idle
set importFolder to (path to downloads folder as text) & "uploadBABY"
set extensionsList to {"jpg", "png", "tiff"}
tell application "Finder" to set theFiles to files of folder importFolder whose name extension is in extensionsList
if (count theFiles) < 1 then
display dialog "No images selected!" buttons "OK"
else
set theFile to some item of theFiles
set albumName to "testscript"
set imageList to {theFile as alias}
tell application "Photos"
activate
delay 2
if not (exists container albumName) then
set theAlbum to make new album
set name of theAlbum to albumName
else
set theAlbum to container albumName
end if
import imageList into theAlbum skip check duplicates yes
end tell
tell application "Finder" to move theFile to trash
end if
return 7
end idle
Code snippet:
tell application "Finder" to set new_item to ¬
(container of this_item as string) & (name of this_item) & "s"
save this_image in new_item as typ
Its saving the file as filename.pngs I want it to save as filenames.png. Any ideas how to fix this?
Save this as an application, then you can drop things on it and it will copy them adding an s to the name. Or you can double-click it and it will ask you to choose a file to copy. NOTE: change the property appendText if you want to change the text (i.e. "s") that's added to the name.
Notice the handler getName_andExtension(f). That's what I use to get the name and extension from a file. I use that to calculate the new path when adding the s.
I hope that helps!
property appendText : "s"
on run
set f to choose file
duplicateInPlace_appendingText(f, appendText)
end run
on open the_items
repeat with f in the_items
duplicateInPlace_appendingText(f, appendText)
end repeat
end open
on duplicateInPlace_appendingText(f, textToAppend)
set f to f as text
set {nm, ex} to getName_andExtension(f)
tell application "Finder" to set theContainer to (container of item f) as text
if ex is "" then
set new_path to theContainer & nm & textToAppend
else
set new_path to theContainer & nm & textToAppend & "." & ex
end if
do shell script "cp -R " & quoted form of POSIX path of f & space & quoted form of POSIX path of new_path
end duplicateInPlace_appendingText
on getName_andExtension(f)
set f to f as text
set {name:nm, name extension:ex} to info for file f without size
if ex is missing value then set ex to ""
if ex is not "" then
set nm to text 1 thru ((count nm) - (count ex) - 1) of nm
end if
return {nm, ex}
end getName_andExtension
name of this_item gives the full name of the Finder item, including the file extension. You need to split it up. Unfortunately, this isn't as easy as it could be. You could do something like:
tell application "Finder"
get the selection
set {dispname, ext, exthidden} to {displayed name, name extension, extension hidden} of item 1 of the result
end tell
if exthidden then
dispname & "s." & ext
else
((characters 1 through -(2 + (count of ext)) of dispname) as string) & "s." & ext
end if
That just builds the modified name for the first item in the Finder selection, without doing anything with it.