Perform an automatic Save As in Preview - applescript

I'd like to have Preview open a pdf and save it to another folder, or save it with a different name to the same folder (not sure which method is needed yet).
I can open the file fine from a specific folder location.
I tried invoking the Save As command, but I don't want the user to have to perform this step, I want to do it automatically to avoid user data entry errors.
Here are the steps that work:
set the save_location to "/FolderOne/FolderTwo/FolderThree/"
set the file_name to "Past Due.pdf"
tell application "Preview"
open file "FolderOne:FolderTwo:Past Due.pdf"
tell application "Preview" to activate
tell application "System Events" to keystroke "S" using {option down, shift down, command down}
end tell

This following AppleScript code will display a dialog for you to choose your original PDF file to be duplicated, display a dialog for you to name your duplicated file, and display a dialog for you to choose a location to save your duplicated file. It will then open your duplicated file in Preview.app, leaving your original un-opened.
This AppleScript code works for me using the latest version of macOS Mojave.
property originalLocation : missing value
property originalFileName : missing value
property originalFileNameExtension : missing value
property moveToLocation : missing value
property newFileName : missing value
activate
set originalFile to (choose file with prompt ¬
"Choose Which Document To Duplicate & Open In Preview.app")
tell application "System Events"
set fileInfo to originalFile's properties
set {originalFileName, originalFileNameExtension, originalLocation} to ¬
{name of fileInfo, name extension of fileInfo, (path of fileInfo) as alias}
end tell
set theOffset to offset of originalFileNameExtension in originalFileName
set shortName to text 1 thru (theOffset - 2) of originalFileName
activate
set newFileName to text returned of (display dialog ¬
"Choose A Name For Your Duplicate File" default answer ¬
(shortName & " Copy") as text buttons {"Cancel", "OK"} ¬
default button 2 cancel button 1 ¬
with title "Choose A Name For Your File" with icon 1 ¬
giving up after 120) & "." & originalFileNameExtension
activate
set moveToLocation to (choose folder with prompt ¬
("Choose A Save To Location For " & newFileName) ¬
default location originalLocation) as text
do shell script "cp " & quoted form of POSIX path of originalFile & ¬
" " & quoted form of POSIX path of ((moveToLocation & newFileName) as text)
do shell script "open -b com.apple.Preview " & ¬
quoted form of POSIX path of ((moveToLocation & newFileName) as text)

Related

How to reveal default Safari downloads folder through Applescript?

I am new to AppleScript and would like to know how to reveal the default downloads folder in Safari through AppleScript.
--- WHAT I HAVE ALREADY TRIED ---
set filePath to do shell script "defaults read com.apple.Safari DownloadsPath"
do shell script "open " & quoted form of filePath
The above script to my understanding will set the variable "filePath" to Safari's default PList entry in preferences.
This works great as long as the location is NOT somewhere within the user home folder. If its within a user folder, the Log shows me a "~/" before the path with no reference to anything prior to the user home folder (relative path)
How do i accomplish my goal? is there a way to get the absolute path to the folder? Or perhaps an alternative method?
Based on #WilliamTFroggard's answer:
tell application "Finder"
set folderPath to do shell script "defaults read com.apple.Safari DownloadsPath"
if folderPath = "~" or folderPath starts with "~/" then ¬
set folderPath to text 1 thru -2 of POSIX path of (path to home folder) & rest of characters of folderPath
open POSIX file folderPath as alias
activate
end tell
The text element is used to strip the trailing / from the home folder (/Users/johndoe/).
The rest property returns every character following the ~ in folderPath (~/Downloads).
/Users/johndoe + /Downloads = /Users/johndoe/Downloads.
You can do this by Applescript GUI Scripting to make Applescript click the 'show downloads' option from the 'view' menu:
tell application "Safari"
activate
end tell
tell application "System Events"
tell process "Safari"
tell menu bar 1
tell menu bar item "view"
tell menu "View"
click menu item "Show downloads"
end tell
end tell
end tell
end tell
end tell
Here's a method using Python:
do shell script "python -c \"import os; print os.path.expanduser('`defaults read com.apple.Safari DownloadsPath`')\""
If you really want the long AppleScript method, try this:
set filePath to ""
set AppleScript's text item delimiters to "/"
set filePathWords to words of (do shell script "defaults read com.apple.Safari DownloadsPath")
if item 1 of filePathWords is "~" then
set item 1 of filePathWords to (POSIX path of (path to home folder as string))
set filePath to filePathWords as string
else
set filePath to "/" & filePathWords as string
end if
If that second "/" in the path bothers you (it sort of bothers me...), you can use this instead:
set filePath to ""
set AppleScript's text item delimiters to "/"
set filePathWords to words of (do shell script "defaults read com.apple.Safari DownloadsPath")
if item 1 of filePathWords is "~" then
set item 1 of filePathWords to (do shell script "cd ~ && pwd")
set filePath to filePathWords as string
else
set filePath to "/" & filePathWords as string
end if
I think what you want is this:
tell application "Finder"
activate
open ("/Users/yourname/Downloads" as POSIX file)
end tell
Just replace "yourname" with your name in Finder.

Struggling to reference cliclick (stored in the same location as script) within applescript workflow

I've been writing a workflow for Alfred 2 which takes a selected jpeg on the users desktop - inserts it to google chrome then use cliclick to right click and reverse search the image via google search.
I cant seem to avoid having the user to put the cliclick in there home folder any attempt to reference the file elsewhere seems to return a systems events error in applescript.
Any help would be appreciated! (I'm extremely new to applescript and alfred apologises if this is a very simple problem)
--get location of selected folder
tell application "Finder"
set sel to the selection as text
set the clipboard to POSIX path of sel
end tell
activate application "Google Chrome"
--open selected jpeg in google chrome
tell application "System Events" to tell process "Google Chrome"
delay 1
keystroke "t" using command down
keystroke "v" using command down
key code 36
delay 1
-- calculate the top left corner of the image
set myBounds to bounds of window 1 of application "Google Chrome"
set x to item 1 of myBounds
set y to item 2 of myBounds
--locate cliclick in users home
set uHome to get path to home folder
set locHome to POSIX path of uHome
--run the right click -> search by image mouse event
do shell script "" & locHome & "/cliclick m:" & x & "," & y & "w:100 kd:ctrl c:+2,+74 ku:ctrl w:1000 c:+66,+90 w:700"
end tell
--close "file://" tab
tell application "Google Chrome"
set windowList to every tab of every window whose URL starts with "file://"
repeat with tabList in windowList
set tabList to tabList as any
repeat with tabItr in tabList
set tabItr to tabItr as any
delete tabItr
end repeat
end repeat
end tell
I tried using
set UnixPath to POSIX path of ((path to me as text) & "::" & "cliclick")
in replacement of
set uHome to get path to home folder
set locHome to POSIXpath of uHome
but replacing it into the shell script with
do shell script "" & UnixHome & " m:" & x & "," & y & "w:100 kd:ctrl c:+2,+74 ku:ctrl w:1000 c:+66,+90 w:700"
stops the workflow with the System Event error
The Script as it stands (cl.ly link)
You could put cliclick in the resource folder of your app and call it like this:
set pathtocc to quoted form of (POSIX path of (path to resource "cliclick"))
do shell script pathtocc & " -h"
Or let curl do the job:
set imagefile to POSIX path of ¬
(choose file of type "public.image" default location path to desktop)
do shell script "
open -a 'Google Chrome' $(curl -F 'encoded_image=#" & imagefile & ¬
"' https://www.google.com/searchbyimage/upload | grep 'tbs=sbi' | sed 's/^.*http/http/;s/\".*$//')"
curl -F uploads the file to reverse search. The output is a redirect which includes the URL to the google result page.

Using Automator or Applescript or both to recursively print documents to PDF

I have a massive set of files (4000+) that are in an old Apple format (Appleworks). My employed needs them all updated to PDF. By opening the documents in Appleworks and using the system print dialogue, I can save them to PDF—this is ideal. I'm a complete nub with Applescript/Automator, however.
Using a Python script I was able to gather all the Appleworks files from my bosses computer and put them in a directory; each file is then in a subdirectory with a .txt file containing its original location (where, eventually, I will have to put them back).
I need the script to move recursively through this massive directory, getting every file that's neither a folder nor a .txt document, and save it to PDF in the same directory in which the original file was found. ie.
/Appleworks/Boss_File_1/
will contain
/Appleworks/Boss_File_1/Boss_file_1.cwk and
/Appleworks/Boss_File_1/path.txt
But must eventually also contain /Appleworks/Boss_File_1/Boss_File_1.pdf
I can get half way with either solution, but don't know how to make them work together. The Applescript I'm using looks like:
set appleworksFolder to choose folder
tell application "Finder"
set folderItems to (files of entire contents of appleworksFolder)
repeat with I from 1 to number of items in folderItems
set the_doc to item I of folderItems
if name of the_doc is not "path.txt" then
try
tell application "AppleWorks 6"
open the_doc
tell application "System Events"
tell process "Appleworks"
keystroke "p" using command down
click menu button "PDF" of window "Print"
click menu item "Save as PDF…" of menu 1 of menu button "PDF" of window "Print"
click button "Save" of window "Save"
end tell
end tell
end tell
end try
else
tell application "Finder"
delete the_doc
end tell
end if
end repeat
end tell`
This opens the print dialogue but never gets any further and I have no idea why. I realize this script also doesn't deal with putting the document back in its original folder, but in Applescript I could easily enough do this if I could get past the actual printing-to-PDF bit.
Meanwhile, in Automator, using this workflow:
Get Specified Finder Items
Get Folder Contents
Filter Finder Items (by kind and then by file extension is not .txt)
Open Finder Items (with Appleworks)
I then am stuck; using the actual Print Finder Items and choosing Adobe PDF seems to actually do nothing at all, and recording myself using the print to pdf process live is useless because I don't know how to get Automator to retain the path the file originated from and ensure it prints to it.
If anyone can help me put this together somehow, I'd be enormously grateful. Thanks.
Convert using Pages
If you have Pages (part of iWork), it can open .cwk files and save them as PDF: just replace your if block with this:
if (the_doc's name extension is not "txt") then
set newName to my makeNewFileName(the_doc, "pdf")
try
tell application "Pages"
open (the_doc as alias)
set thisDoc to front document
save thisDoc as "SLDocumentTypePDF" in newName
close thisDoc saving no
end tell
on error
display dialog "Error: cannot export " & (name of the_doc) & " to PDF."
end try
end if
(you will need this custom function makeNewFileName):
(* prepare new file name with extension ext *)
on makeNewFileName(finderItem, ext)
tell application "Finder"
set fname to finderItem's name
set thePath to (finderItem's container) as alias as text
return (thePath & (text 1 thru ((length of fname) - (length of (finderItem's name extension as text))) of fname) & ext)
end tell
end makeNewFileName
(complete working script)
GUI scripting
Alternatively, you could do GUI scripting upon AppleWorks as you attempted, but it has the disadvantage that you cannot programmatically specify where to save the PDF file.
This snippet works for me:
tell application "AppleWorks 6"
open the_doc
activate
tell application "System Events" to tell process "AppleWorks"
keystroke "p" using command down
delay 1 -- or longer, if it takes longer
click menu button "PDF" of window "Print"
click menu item "Save as PDF…" of menu 1 of menu button "PDF" of window "Print"
delay 1 -- or longer
click button "Save" of window "Save"
end tell
end tell
Unfortunately, AppleWorks doesn't seem to properly listen to AppleScript's close command, therefore you may need to close the file by also simulating the cmd+W keystrokes.
Try this:
set appleworksFolder to choose folder
set thePath to POSIX path of appleworksFolder as string
tell application "Finder"
set folderItems to files of appleworksFolder
repeat with aFile in folderItems
set {name:fileName, name extension:nameExtension} to aFile
set filePath to POSIX path of (aFile as alias) as string
if nameExtension is not "txt" then
set theLocation to POSIX path of (aFile as text)
set baseName to text 1 thru ((get offset of "." & nameExtension in fileName) - 1) of fileName
set destLocation to (thePath & baseName & ".pdf")
set theCommand to "/System/Library/Printers/Libraries/./convert -f \"" & filePath & "\"" & " -o " & "\"" & destLocation & "\"" & " -j \"application/pdf\""
do shell script theCommand
else
tell application "Finder" to delete aFile
end if
end repeat
end tell
I needed to do this today on Mountain Lion with a bunch of RTF receipts; here's how I did it:
#!/bin/bash
for file in *.rtf ; do
filename=$(basename "$file")
/usr/sbin/cupsfilter "$file" > "$filename.pdf"
done
Worked great; super easy. No Automator or AppleScript silliness.

applescript: how to automatically choose to save a safari document at a PARTICULAR PATH with system events

I want to make a script that will save safari documents using system events (command+s) and I want the file to always be saved at a particular path. (I could make a habit of always saving safari files at a certain folder but that's not a robust solution) How can I make sure system events saves a document at a certain path?
Directly from this MacRumors forum post:
tell application "Safari"
activate
end tell
tell application "System Events"
tell process "Safari"
click menu item "Copy" of menu "Edit" of menu bar 1
end tell
end tell
delay 1
set the_filename to (the clipboard) & ".html"
set the_filepath to "Macintosh HD:Users:Roy:Documents:" & the_filename
set the_shellfilepath to "'/Users/Roy/Documents/" & the_filename & ".download'"
set the_shellfilepath2 to "'/Users/Roy/Documents/" & the_filename & "'"
tell application "Safari"
activate
save document 1 in the_filepath
end tell
do shell script "mv " & the_shellfilepath & " " & the_shellfilepath2
Set the path (the_shellfilepath) as appropriate.
Changing the folder of a file dialog:
try
try -- this would result in an error when there's no clipboard
set old to the clipboard
end try
-- delay 1 -- for testing
-- activate application "Safari"
tell application "System Events"
keystroke "s" using command down
keystroke "g" using {shift down, command down}
delay 0.1
set the clipboard to "~/Movies/"
delay 0.1
keystroke "av" using command down
delay 0.1
keystroke return
delay 0.1
end tell
set the clipboard to old
end try
Saving to a specific folder with a partially encoded URL as a file name:
tell application "Safari"
set x to URL of document 1
set r to do shell script "echo " & quoted form of x & " | sed 's|/$||;s|:|%3A|g;s|/|%2F|g'"
do shell script "curl " & x & " > " & quoted form of ((system attribute "HOME") & "/Desktop/" & r & ".html")
end tell
Saving to a specific folder but choosing the file name manually:
tell application "Safari"
set x to URL of document 1
set answer to text returned of (display dialog "" default answer ".html")
do shell script "curl " & x & " > " & quoted form of ((system attribute "HOME") & "/Desktop/" & answer)
end tell

AppleScript Focus / Rename File (and clicking anywhere)

on run {input}
set filepath to POSIX path of input
do shell script "touch " & quoted form of filepath & "untitled"
return input
end run
Is what I have so far, and it works, but is there a way to then focus on the file then trigger a rename? I dont want the rename to be automatic, just trigger the event (like pressing "return" while you have a file selected). And I dont want to use any sort of modal...
Quick Side question: is there a way to set this so that i dont have to select a folder or file directly, but can do it by, lets say, clicking in a white space in a folder as long as it's in Finder? Right now I have my "Service receives selected" to "files or folders" in Finder.app.
== UPDATED CODE ==
on run {input}
set filepath to POSIX path of input
do shell script "touch " & quoted form of filepath & "untitled"
tell application "Finder"
activate
set target of Finder window 1 to POSIX file "/Users/oscargodson/Documents/designs/untitled"
end tell
tell application "System Events"
tell process "Finder"
keystroke return
end tell
end tell
return input
end run
If i hardcode the path it works! But how do I get it as a var that works?
Here's one way. I think a modal window where you ask for the name would be better but you can try this. Notice you do not use "POSIX path" in this code. Applescript doesn't use POSIX paths. Also {input}, as indicated by the brackets around it, is a list of items. Therefore you act on the items of the list, and in this case we act on the first item.
set filepath to item 1 of input
tell application "Finder"
activate
reveal filepath
end tell
tell application "System Events"
tell process "Finder"
keystroke return
end tell
end tell
EDIT: With your updated code, here's a working script...
on run {input}
if (class of input) is not list then set input to {input}
set theFolder to (item 1 of input) as text
try
alias theFolder
tell application "Finder"
if (class of item theFolder) is not folder then error "input is not a folder."
activate
set theFile to make new file at folder theFolder with properties {name:"untitled"}
reveal theFile
end tell
delay 0.2
tell application "System Events"
tell process "Finder"
keystroke return
end tell
end tell
on error theError number errorNumber
tell me
activate
display dialog "There was an error: " & (errorNumber as text) & return & return & theError buttons {"OK"} default button 1 with icon stop
return
end tell
end try
return input
end run
tell application "Finder"
activate
reopen -- in case there are no open windows
set target of Finder window 1 to POSIX file "/Applications/Safari.app"
end tell
reveal and select always open a new window, set target and set selection don't.
I don't know why, but when set selection it used in column view, you can only select items in the entire contents of the target of the front window. The same thing doesn't happen in other views, so it seems like a bug.
Fix for the code in the edited question:
on go(input)
set p to POSIX path of (input as text)
set p2 to p & "untitled"
do shell script "touch " & p2
tell application "Finder"
reopen
activate
set target of Finder window 1 to POSIX file p2
end tell
delay 0.3 -- time to release modifier keys
tell application "System Events" to keystroke return
end go
tell application "Finder"
set fold to folder (path to documents folder)
end tell
go(fold)
(That on go and the last lines are just for testing.)
I've created an AppleScript based on the #regulus6633's one, but with some improvements.
Note: This answer was originally posted as an AskDifferent answer. I'm copy/pasting here for convenience.
The idea is to create an Automator workflow and assigning a shortcut to it using the following steps:
Open Automator and create a Service;
Set the input to no input, and the application to Finder.app;
Drag and Drop the Run AppleScript workflow element onto the grey space;
Put the contents of this AppleScript in the textbox;
Save the workflow with a reasonable name (like New File);
Go to Settings -> Keyboard -> Shortcuts -> Services and assign a shortcut to it.
Now, let's show the AppleScript:
set file_name to "untitled"
set file_ext to ".txt"
set is_desktop to false
-- get folder path and if we are in desktop (no folder opened)
try
tell application "Finder"
set this_folder to (folder of the front Finder window) as alias
end tell
on error
-- no open folder windows
set this_folder to path to desktop folder as alias
set is_desktop to true
end try
-- get the new file name (do not override an already existing file)
tell application "System Events"
set file_list to get the name of every disk item of this_folder
end tell
set new_file to file_name & file_ext
set x to 1
repeat
if new_file is in file_list then
set new_file to file_name & " " & x & file_ext
set x to x + 1
else
exit repeat
end if
end repeat
-- create and select the new file
tell application "Finder"
activate
set the_file to make new file at folder this_folder with properties {name:new_file}
if is_desktop is false then
reveal the_file
else
select window of desktop
set selection to the_file
delay 0.1
end if
end tell
-- press enter (rename)
tell application "System Events"
tell process "Finder"
keystroke return
end tell
end tell
For convenience, I'm putting this AppleScript in this GitHub Gist.

Resources