I'm brand new to AppleScript and I'm trying to write a basic script that does the following:
Finds images (PNGs) in the folder ~/Dropbox/Camera Uploads that are exactly 640x1136 (iPhone 5 screenshots) and moves them to ~/Dropbox/Camera Uploads/Screenshots.
This seems pretty straightforward, but so far I haven't been able to figure it out.
Here's how I would do it. I wouldn't worry about performance. I ran the Image Events section on 200 files, and it only took 1 second.
set picFolder to alias "Path:to:Dropbox:Camera Uploads:"
set screenshotFolder to alias "Path:to:Dropbox:Camera Uploads:screenshots:"
tell application "System Events"
set photos to path of files of picFolder whose kind is "Portable Network Graphics image"
end tell
set screenshots to {}
repeat with imgPath in photos
set imgAlias to alias imgPath
tell application "Image Events"
set img to open imgPath
if dimensions of img = {640, 1136} then
set end of screenshots to imgAlias
end if
close img
end tell
end repeat
tell application "Finder"
move screenshots to screenshotFolder
end tell
You need to have an AppleScript-aware application that can act based on the dimensions of an image file. I don’t think the Finder can do this, despite its ability to show the dimensions of images in Finder views.
iPhoto should be able to do this. The iPhoto dictionary indicates that “photos” have both the width and height of images. So you should be able to write an AppleScript that imports them into iPhoto first, then selects those that match your criteria, and then saves them to the appropriate Dropbox folder.
Depending on your needs, you might also look at Automator. It contains iPhoto actions as well, including one to “Filter iPhoto items”. If you create a Folder Action you should be able to create an Automator script that starts up whenever something new is added to your Camera Uploads folder, adds them to iPhoto, and then copies them to your Screenshots folder.
If nothing else, you should be able to use Image Events to get all images in the folder, and then act only on the ones that match your criteria. Something like:
tell application "Image Events"
tell folder "Macintosh HD:Users:colin:Dropbox:Camera Uploads"
copy (files where kind is "JPEG image") to potentialScreenshots
repeat with potentialFile in potentialScreenshots
set potentialScreenshot to open potentialFile
set imageDimensions to dimensions of potentialScreenshot
if item 1 of imageDimensions is 640 then
set fileName to name of potentialFile
tell me to display dialog fileName
end if
end repeat
end tell
end tell
There ought to be a way to tell Image Events to only look at files whose dimensions match what you want, but I can’t see it.
Try:
set folderPath to POSIX path of (path to home folder) & "Dropbox/Camera Uploads"
set screenshotsPath to POSIX path of (path to home folder) & "Dropbox/Camera Uploads/Screenshots"
try
do shell script "mdfind -0 -onlyin " & quoted form of folderPath & " \"kMDItemPixelWidth == 640 && kMDItemPixelHeight == 1136\" | xargs -0 -I {} mv {} " & quoted form of screenshotsPath
end try
Related
As you can see from my code below I am extremely new to this. My code just about works, but my major issue is that it hogs up Finder and sometimes it does not set the Desktop picture, but does most of the time!
The script just monitors a folder, and if an "***.jpg" is added then the Desktop picture set to it.
This is my very first script so I have a lot to learn,
set reset to ""
display notification "Alarm Front Active " & (current date) as string
tell application "Finder"
set path_to_sourceFull to ":photo:FRONT CAM 1:20190929:images" -- from nsa310 network drive
set path_to_source to ":photo:FRONT CAM 1:20190929:images" -- from nsa310 network drive
set directory1 to "/Volumes/photo/FRONT CAM 1/20190929/images" as text -- from nsa310 network drive
set path_to_destinationFull to "Macintosh HD:Users:rekordbox:Documents:temp folder 2"
set path_to_destination to ":Users:rekordbox:Documents:temp folder 2"
set directory2 to "/Users/rekordbox/Documents/temp folder 2" as text
repeat while reset = ""
set allok to ""
set filelist to name of every item in folder path_to_source --of startup disk
set listSizesaved to count of filelist
delay 1
repeat while allok = ""
set filelist to name of every item in folder path_to_source --of startup disk
set listSize to count of filelist
if listSize = listSizesaved then
else
set filelist to name of every item in folder path_to_source --of startup disk
set listSize to count of filelist
set LastAddedFile to item listSize of filelist
set allok to "ALARM"
set listSizesaved to listSize -- (save the updated) count
set activefile to (path_to_source & LastAddedFile)
set selectedpicture to (directory1 & "/" & LastAddedFile)
tell application "System Events" to tell every desktop to set picture to selectedpicture
delay 1
display notification "ALARM FRONT TRIGGERED...." & (current date) as string
delay 1
end if
end repeat
end repeat
end tell
The script you want, I think, is this:
on adding folder items to thisFolder after receiving filelist
set droppedFile to first item of filelist
tell application "System Events"
tell every desktop
set picture to droppedFile
end tell
end tell
end adding folder items to
(I've left out the 'Alarm' bit, since I wasn't sure what the point of it was.)
To use this script, copy it into Script Editor, save it in the folder ~/Library/Scripts/Folder Action Scripts/, then open the applet 'Folder Actions Setup'. Add the folder you want on the left-hand side, and choose the file you just saved on the right. It should look something like this:
...where the checkmark on the left shows that folder actions are enabled for the folder (which I called 'test folder') and the script (which I called 'FADtop.scpt') is attached.
Drop an image in the folder, and it should just work.
As a general rule, don't script the Finder unless you absolutely need to; always use System Events. The Finder is a busy app, and scripting it can gum up the system. And also try to avoid this design pattern:
(* Don't do this! *)
repeat
(* test for something *)
delay x
end
The delay command is not particularly resource-efficient. If you really want to use a polling system to test for some event, it's often better to create a stand-alone app with an on idle handler. That way you let the system wake and sleep the script, with significant performance improvements.
EDIT
Since folder actions don't seem to be working with ftp drops onto remote drives, here's a reasonably efficient folder-polling approach. Save the following script as a stay-open application (choose 'Application' as the file type, and click the 'stay open' checkbox). Then launch the application and leave it running in the background.
property dateOfLastFileChosen : missing value
property targetFolder : "/Volumes/photo/FRONT CAM 1/20190929/images"
property idleTime : 300 -- 300 seconds is five minutes
on run
end run
on idle
tell application "System Events"
if exists folder targetFolder then
if dateOfLastFileChosen is missing value then
set recentFiles to every file of folder targetFolder whose visible is true
else
set recentFiles to every file of folder targetFolder whose modification date > dateOfLastFileChosen and visible is true
end if
set newFile to my mostRecentFileOfList(recentFiles)
if newFile is not missing value then
set dateOfLastFileChosen to modification date of newFile
tell every desktop
set picture to (POSIX path of newFile)
end tell
end if
end if
end tell
return idleTime -- check every 5 minutes (300 seconds)
end idle
on mostRecentFileOfList(fileList)
set maxDateObj to missing value
repeat with thisFile in fileList
if maxDateObj is missing value then
set maxDateObj to contents of thisFile
else if modification date of thisFile is greater than modification date of maxDateObj then
set maxDateObj to thisFile
end if
end repeat
return maxDateObj
end mostRecentFileOfList
Without trying to steal the thunder from #Ted Wrigley, whose solution provided the AppleScript code for the folder action, I felt there were enough comments and items for me to add to post it as another answer to the OP's dilemma.
First I will address the tell every desktop set picture to droppedFile lines of code in the following AppleScript Folder Action. If the user has only one monitor/display attached to the computer, but has created several different "Spaces", the tell every desktop set picture to droppedFile lines of code will only change the Desktop Picture for the Desktop of the current active "Space" only. The other Desktop backgrounds will not be changed. However, if the user has several monitors/displays attached to the computer, the tell every desktop set picture to droppedFile lines of code will change the Desktop Pictures for the Desktops of the current active "Space" for each attached monitor/display. If the latter is not the desired result, then tell every desktop should be changed to tell current desktop.
After testing the AppleScript Folder Action code provided by #Ted Wrigley, I noticed the image file being downloaded from an FTP server, to the test folder where I have the folder action script attached to, looked like this before the image was actually finished transferring. Because the file was kind of there and not there, it did not trigger the Folder Action.
Next, I figured I would add a delay to be beginning of the Folder Action code to allow for the transfer of the image file from the FTP server, to complete. I added a delay of 180 seconds to allow for the transfer to complete and it worked. When the transfer was complete, the file look like this.
Depending on how many files you foresee being transferred at any given time along with factoring in for file sizes... It's possible you may need to significantly increase the Delay time.
on adding folder items to thisFolder after receiving theseFiles
delay 180
set newBackground to first item of theseFiles
tell application "System Events"
set picture of current desktop to newBackground -- Single Display Attached
--set picture of every desktop to newBackground -- Multiple Displays Attached
end tell
end adding folder items to
I found many topics on that but none of the solutions seem to fit what i want to do or they don't work.
I want to select multiple images in a folder in a finder window.
I want to right-click the selection and run a Service to create a PDF using those images in the same folder those images are in.
I don't know how to get the directory the images are placed in.
Assuming that your selected file could be from different folders, you must loop to each image and get parent folder as bellow :
tell application "Finder"
set myFIles to selection -- read your selection of images
repeat with aFile in myFIles -- loop for each selecgted image
set ParentFolder to container of aFile -- get folder which contains that image
end repeat
end tell
I always design my presentation slides in keynote (because I find it easier and more pleasant to work with), though they often need to be presented on a windows machine running PowerPoint.
In order to avoid issues with fonts, formatting, etc., I always use the following effective workflow:
Design the slides in keynote, often using images and text.
Export the slides as jpg files to a folder on the desktop.
Open a new keynote presentation.
Drag the jpg files into the slide navigator. This creates an image slide of each jpg.
export the new presentation to a .ppt file.
Is there a way I can automate this workflow? I'd love to collapse steps 2-5 into a single step!
Here's the AppleScript that does this (work on Keynote version 6.2, not on version 5):
tell application "Finder" to set f to (make new folder) as text -- create a temp folder to export images
tell application "Keynote"
tell front document
export to (file f) as slide images with properties {image format:JPEG, compression factor:95}
set {h, w, fPath} to {height, width, file of it}
end tell
tell (fPath as string) to if it ends with ".key:" then
set newFile to (text 1 thru -6) & ".ppt"
else
set newFile to it & ".ppt"
end if
set jpegs to my getImages(f)
set newDoc to make new document with properties {width:w, height:h}
tell newDoc
set mSlide to last master slide -- blank
repeat with thisJPEG in jpegs
set s to make new slide with properties {base slide:mSlide}
tell s to make new image with properties {file:thisJPEG}
end repeat
delete slide 1
export to (file newFile) as Microsoft PowerPoint
close saving no
end tell
end tell
tell application "Finder" to delete folder f -- delete the temp folder
on getImages(f)
tell application "Finder" to return (files of folder f) as alias list
end getImages
Important:
the slideshow must be already open in Keynote before running the script.
And the slideshow must be already saved, because the script use the path of the front document to save the PPT file in the same folder.
--
Updated: to choose location of the new file
set v to ("Volumes" as POSIX file) as alias
tell application "Finder" to set f to (make new folder) as text -- create a temp folder to export images
tell application "Keynote"
tell front document
export to (file f) as slide images with properties {image format:JPEG, compression factor:95}
set {h, w, tName} to {height, width, name of it}
end tell
tell tName to if it ends with ".key" then
set newName to (text 1 thru -5) & ".ppt"
else
set newName to it & ".ppt"
end if
set jpegs to my getImages(f)
activate
set newFile to choose file name default name newName default location v with prompt "Select the folder to save the PPT file"
set newDoc to make new document with properties {width:w, height:h}
tell newDoc
set mSlide to last master slide -- blank
repeat with thisJPEG in jpegs
set s to make new slide with properties {base slide:mSlide}
tell s to make new image with properties {file:thisJPEG}
end repeat
delete slide 1
export to (newFile) as Microsoft PowerPoint
close saving no
end tell
end tell
tell application "Finder" to delete folder f -- delete the temp folder
on getImages(f)
tell application "Finder" to return (files of folder f) as alias list
end getImages
I've encountered a little problem when I wanted to modify a ApplScript, that I am using to get my current iTunes Coverinto a image file that I display on my Desktop via GeekTool.
Now I wanted also to resize this Image because some Images are a bit small...
I found some solutions online, but none of them worked...
And since I am not that much into AppleScript I also can't handle it myself.
This is my current Code:
set the_artwork_file to ((path to home folder) as string) & "Music:iTunes:CurrentArtwork.png"
tell application "System Events"
if ("iTunes" is in name of processes) then
tell application "iTunes"
if (player state is not stopped)
and (player state is not paused)
and (artworks of current track exists)
then
set theArt to front artwork of current track
set pic to (raw data of theArt)
try
set RefNum to (open for access the_artwork_file with write permission)
write (pic) to RefNum
close access RefNum
return
end try
end if
end tell
end if
end tell
do shell script "rm -f " & (POSIX path of the_artwork_file)
Ok, nevermind, I managed to solve it finally.
The Code I generated was basically correct, but I had to put it into an separate Script-File.
In GeekTool I have to call them directly after each other and it works just fine!
This is the Code I used now:
tell application "Image Events"
set this_image to open ((path to home folder) as string) & "Music:iTunes:CurrentArtwork.png"
scale this_image to size 1080
save this_image in ((path to home folder) as string) & "Music:iTunes:CurrentArtwork.png"
close this_image
end tell
i was wondering if anyone can tell me how to make this script work. I tried for hours and i can't figure out why it fails.
This script tells Quicktime to advance in a quicktime movie/presentation (generated by keynote) and export a image for every last frame of every chapter in this movie.
property Main_folder : missing value
set Main_folder to choose folder
tell application "QuickTime Player 7"
if not (exists document 1) then error "No movies are open."
stop movies
tell front document to set {currMovie, T_name, duration_list, current time} to ¬
{it, text 1 thru -5 of (get name), duration of chapters of (get first track whose kind is "Sprite"), 0}
set T_target to my makeFolder(T_name)
repeat with i from 1 to (count duration_list)
tell currMovie
set current time to current time + (item i of duration_list)
export to (T_target & T_name & " Chapter " & i) as picture using settings preset "Photo-JPEG" -- or "Uncommpressed", or "PNG"
end tell
end repeat
end tell
on makeFolder(n)
tell application "Finder" to return (make new folder at Main_folder with properties
My problem here is that it saves the images in PICT format instead of PNG.
The relevat part of the script is here:
export to (T_target & T_name & " Chapter " & i) as picture using settings preset "Photo-JPEG" -- or "Uncommpressed", or "PNG"
I tried it with PNG and and Photo-JPEG only but it still only generates images in the PICT format
Does anyone know how to do this? I can't find any mistakes in the script ... it should work.
Any advice is welcome! Thx in advance.
Best regards,
zhengtonic
update
If anyone is interested i found the reason:
Quicktime 7 is not able to grap a still image from a mov and export it as png/jpeg.
I found a workaround by converting the videos to mp4 and than extracting certain frames.
There's an easier way than re-encoding the movie to mp4. In quicktime you can export an image sequence from a movie. The images of an image sequence can be png images. As such you can applescript this. Here's the basic outline of what you'd need to do. It might seem complicated but it's really pretty simple.
First, Create a settings file for the export as image sequence. You can do that by starting an export and setting up the settings for that. Then run this applescript to save the settings in a file...
set exportFileName to "ImageSequenceExportSettings.qtSettings"
set exportFilePath to (path to desktop as text) & exportFileName
tell application "QuickTime Player 7"
tell first document
save export settings for image sequence to file exportFilePath
end tell
end tell
Second, your applescript takes a time where you want the image, then you basically trim the movie so that it contains only the frame for that time, then you use the settings file to export that frame as your image, something like this... NOTE: I didn't test the following script
set timeOfImage to 60 -- in seconds
set settingsFile to (path to desktop as text) & "ImageSequenceExportSettings.qtSettings"
tell application "QuickTime Player 7"
tell document 1
if (can export as image sequence) then
-- trim the movie to one frame
set ts to time scale
set theFrame to timeOfImage * ts
select at theFrame to (theFrame + 1)
trim
-- save the image
set theName to text 1 thru -5 of (get name)
set outPath to (path to desktop as text) & theName & ".png"
export to outPath as image sequence using settings settingsFile
-- close the movie
close saving no
else
error "The front movie cannot be exported to an image sequence!"
end if
end tell
end tell