AppleScript Read The Keywords In The Preview App - pdf

The Preview App on the Mac lets you add keywords to a PDF file.
Is it possible to use AppleScript to read the keywords? If so, how?

The Exiftool manages keywords for many file types, including PDF. This is a free command line tool you can download. Once the tool is installed, you can use it via Terminal or, of course, via Applescript with "do shell script".
If myFile is the PDF file selected, then you can read the existing keywords with:
set myKeyWords to do shell script "/usr/local/bin/exiftool -Keywords " & quoted form of (POSIX path myFile)
if length of myKeyWords > 35 then
set myKeyWords to text 35 thru -1 of myKeyWords
end if
The result of the command is empty (if no keywords) or it is made of 33 spaces, ':', 1 space, and the list of keywords separated by ','. This is why I added the 'if' statement after the do shell script command.
And you can also write new keywords (variable MyKey) in your PDF file with :
do shell script "/usr/local/bin/exiftool -Keywords+='" & MyKey & "' -Overwrite_Original " & quoted form of (POSIX path of myFile)
Exiftool can do many other things for images and PDF files. Some actions are specific to images, some to PDF, or for all file types. Please use the man page in Terminal to know more.

Preview.app supports only the generic classes / commands and has no application specific dictionary.
It might be possible with the ugly GUI scripting.

Related

applescript to move files in numeric order

i started a project for a friend, that involved moving large quantities of files into specific folders. i was using automator as I'm handling the project on my mac, however automator does not have a feature to move section of files that are numbered numerically. for instance i will have files that are say "this file 100" and ill have 100 files like that. and then files that say "That file 50" and ill have 200 files like that. the project is splitting these files into there own folder but in section. so ill need "This file" 1-25 in one folder 26-80 in anther and so on. same is true for the "THAT FILES" but there isn't a pattern just the requirement my friend has asked for.
is there a easy way to write a script that could grab 1-25 or any sequel ordering with the same file name? because moving each file one at a time with automator has been taking to long.
thank you so much in advanced
I am not sure tu fully understand your naming convention, but overall , yes, with Applescript, you can move files into folders based on names, eventually adding sequence numbers.
Because I am not sure about your requirements, at least, here are some sample of syntax for main operations :
Get list of files with names containing xxx in folder myFolder :
Tell Application "Finder" to set myList to every file of myFolder whose name contains "xxx"
Then you have to do a repeat / end repeat loop :
Repeat with aFile in myList
-- do something here with aFile : example with name of aFile
end repeat
In that loop you can extract name, parse it, add a counter,...
To move file to new folder, you must use "move" instruction in a tell "Finder" bloc. Instruction "make" can also be used to create new destination folder based on name or root names of files. You must remember that Applescript commands will give error if same file name already exists in destination folder : Finder is able to add "copy" in the name, but you must do it yourself in Applescript.
Last advice if about the number of files to handle. If that number is not so high (less than few hundreds) Applescript is still OK for speed. If your number of files is much higher, then you must use either shell command or, better, a mix of AS and shell commands. The shell commands can be called from AS with a "do shell script". For instance, getting the list of 1000 files from a folder is time consuming with AS, but much quicker with 'ls' command ! Same for a copy. here is an example of copy using shell 'cp' :
do shell script "cp " & quoted form of (POSIX path of (aFile as string)) & " " & quoted form of (POSIX path of DestFolder) & (quoted form of newFileName)
Note : "Posix path" converts the AS file path (Users:myName:Documents:File.txt) into shell path (Users/myName/Documents/File.txt)
I hope it helps.

Mac OS app based on Applescript

I'm new to Xcode as well as I am to AppleScript
All I need is to run an AppleScript in an Xcode application.
Bassically, the application is downloading pictures from a url list in Excel and renames the files acording the list in Excel
Here is the applescript code :
tell application "Microsoft Excel"
set filenames to value of every cell of range "K3:K200" of sheet "Image_Moves" of document 1
set URLs to value of every cell of range "L3:L200" of sheet "Image_Moves" of document 1
end tell
repeat with i from 1 to count URLs
if (item i of filenames is not missing value) and (item i of URLs is not missing value) then
set thisFname to quoted form of (POSIX path of ({path to desktop, "Image_Moves:"} as text) & item i of filenames)
set thisUrl to quoted form of item i of URLs
set status to (do shell script "curl -s -o " & thisFname & space & thisUrl)
end if
end repeat
try
tell application "Finder"
delete (every item of folder ("Image_Moves") whose name begins with "0")
end tell
on error
display dialog ("Error. Couldn't Move the File") buttons {"OK"}
end try
In Xcode, you can write a full application in AppleScript with the "Cocoa-AppleScript" template. Also, you can compile and execute an AppleScript with the NSAppleScript class. If your question is just about making an AppleScript executable, use Save As... in Script Editor and save your AppleScript as an application.
HTH

FTP Shell - Get all files that do not equal a condition

I'm currently using VBA (Excel) to call the FTP Shell to grab files from a directory. I want to grab all files in the directory that do not contain the wildcard %payment%, but I'm not sure of the syntax.
Sub executeFTPBatch()
Call Shell("FTP -i -s:C:\temp\ftp_directions.txt")
End Sub
So my text file opens the FTP server, inputs the user/pw and then selects the directory. I just need the command to put into the text file. Something like
mget *. * where filename != %payment% "c:\temp\" "ftp://currentfolder"
Any help would be greatly appreciated!
I'm not sure, what is "wildcard %payment%".
Though the built-in Windows ftp.exe does not support negative masks in any way.
I can suggest these solutions:
Run the ftp.exe once to get a directory listing (the ls command); parse the listing in your VBA code; select the files you want; and dynamically generate another ftp script to download these files.
Use another command-line FTP client, that supports negative masks.
For example with WinSCP scripting you can do:
Call Shell( _
"C:\path\WinSCP.com /log=C:\path\excel.log /command " & _
"""open ftp://user:password#example.com/"" " & _
"""get /path/* C:\path\ -filemask=|*%payment%*"" " & _
"""exit""")
To ease reading, the above runs these WinSCP commands:
open ftp://user:password#example.com/
get /path/* C:\path\ -filemask=|*%payment%*
exit
If you prefer, you can put the commands to a script file and run the script with the /script= command-line parameter, similarly to the ftp -s:, instead of the /command.
See the guide to Converting Windows FTP script to WinSCP script.
See also WinSCP file mask reference.
Alternatively you can use WinSCP .NET assembly via COM from the VBA code.
(I'm the author of WinSCP)

Embed Applescript in Global Field to (Export Container and Trigger Printing with Acrobat)

I am trying to tie together a filemaker script that will export PDFs to a temporary space and use and apple script to print them.
I was able to cull together info from this and some other boards to create an applescript that will print the PDFs using Acrobat from a folder.
I have already created a script that finds the Related attachments and exports them to the desktop.
What I'm having trouble with is merging the two.
I need to export the PDF to a folder or temporary place and trigger the apple script to initiate the printing...
This great Suggestion was provided by Chuck of chivalrysoftware.com/…...
Calculate the location to export by appending the filename to Get( TemporaryPath ).
Export the container field contents to FileMaker to that path.
Save the path to a global field in FileMaker
Use an embedded AppleScript to access the global field path
Use AppleScript to open the file in Preview and print it
This is my apple script:
set myFolder to (path to desktop folder as text) & "Print:"
set myfiles to list folder myFolder without invisibles
repeat with myfile in myfiles
set mycurrentfile to ((myFolder as string) & (myfile as string)) as string
batchprint(mycurrentfile)
end repeat
on batchprint(mycurrentfile)
tell application "Adobe Acrobat Pro"
activate -- bring up acrobat
open alias mycurrentfile -- acrobat opens that new file
tell application "System Events"
tell process "Acrobat"
click menu item "Print..." of menu 1 of menu bar item "File"¬
of menu bar 1
click button "Print" of window "Print"
tell application "System Events"
tell process "Acrobat"
click menu item "Close" of menu 1 of menu bar item "File"¬
of menu bar 1
end tell
end tell
end tell
end tell
end tell
tell application "Finder" -- to move the printed file out
set x to ((path to desktop folder as text) & "Printed PDFs:")
if alias x exists then
beep
else
make new folder at the desktop with properties {name:"Printed PDFs"}
end if
move alias mycurrentfile to folder "Printed PDFs"
end tell
end batchprint
My Filemaker script is:
Go to Related Record[
Show only related records; From table: 'Attachments";
Using layout: "Attachements Report' (Attachments); New window
]
Enter Find Mode
Constrain Found Set [Restore]
Sort Records [Restore; No dialog]
# After finding the related attachments and constraining them to the specific type
# we rename and export them to the desktop
Go to Record/Request/Page [First]
Loop
Set Variable [$Path; Value:
Get ( DesktopPath ) & Attachments::Record number & "-"
& Attachment Type List 2::Prefix_z & Lien::Lien_ID_z1]
Export Field Contents [Attachments::file_c; $Path]
Go to Record/Request/Page [Next: Exit after last]
End Loop
Close Window [Current Window]
First of all, the FileMaker part. Create a global text field in one of your tables. It looks like the Attachments table would be the best place for it. I'll call it g_applescript_parameter for this.
Now we're going to use your $Path variable, which given the calc you've provided should be something like /Aslan/Users/chuck/Desktop/1234-ABC4321. I'd recommend appending a .pdf to the end of it since you'll be exporting PDF files. This may help later.
Also, I would recommend that you use Get( TemporaryPath ) instead of Get( DesktopPath ). Anything you place in the temporary folder will be automatically deleted when you quit FileMaker, which means you don't have to write anything to clean up the desktop folder later and you don't have to manually trash them either. Let FileMaker do that work for you. :)
Regardless, FileMaker uses a path of the form filemac:/volumeName/directoryName/fileName (see the notes in the Specify output file dialog box for the Export Field Contents script step). So you should also prepend filemac: to the beginning of your path variable.
All told, your $Path should be set to something like this:
"filemac:" & Get( DesktopPath ) & Attachments::Record number & "-" &
Attachment Type List 2::Prefix_z & Lien::Lien_ID_z1 & ".pdf"
So your export path for FileMaker should work better now. But AppleScript requires a different format for the path to the same file. Given the above, AppleScript's version should be something like /Users/chuck/Desktop/1234-ABC4321.pdf. In other words, everything after the drive name. Fortunately FileMaker can get the drive name with the Get( SystemDrive ) function. For me that function returns /Aslan/. So if we take the $Path variable as defined above and remove filemac: and the name of the drive as defined by Get( SystemDrive ) and add an extra slash at the beginning, that would convert our FileMaker path into an AppleScript path:
"/" & Substitute( $Path; "filemac:" & Get( SystemDrive ); "" )
Use Set Variable to create an $ASPath variable and set it to the above.
Now within your loop store the contents of the $ASPath variable within that global text field:
Loop
Set Variable[ $Path; …]
Set Variable[ $ASPath; …]
Set Field[Attachments::g_applescript_parameter; $ASPath)
Export Field Contents[Attachments::file_c; $Path]
Go to Record/Request/Page[Next; Exit after last]
End Loop
Now AppleScript can extract that information. I'm assuming that given an accurate file being passed to the batchprint function, batchprint will work, so keep that, but remove everything before it and use something like this:
set _pdf_path to contents of cell "g_applescript_parameter" of current layout
batchprint(_pdf_path)
on batchprint(mycurrentfile)
...
end batchprint
Add a Perform AppleScript step after the Export Field Contents step and place the above code in it.
Note that the first line of the above AppleScript will only work as written from within FileMaker. If you're testing this outside of FileMaker in, for example, Script Editor, then you'll need to make that first line read
tell applicaiton "FileMaker" to set _pdf_path ...
You don't need to do this within the Perform AppleScript script step because by default commands are sent to the enclosing FileMaker application.

AppleScript path being replaced at compile time (New Keynote scripting trouble)

We've got an applescript that tells keynotes to delete slides based on criteria. The new keynote does not have an applescript dictionary, but leaves the old keynote in a subdirectory. So I'm trying to tell AppleScript to talk with the older app rather than the new one.
If I just
tell application "Clean Install:Applications:iWork '09:Keynote.app"
It works, but it doesn't recognize any of the keynote dictionary terms. (delete a slide). So I need to pull out my old friend "using terms from". The challenge here is that this is a precompile directive, so you have to use a string literal, which I don't have on the end user's machine due to different hard drive names.
Ok, still have a plan here. I will write out a new applescript file with the 'using terms from application "Clean Install:Applications:iWork '09:Keynote.app"' and then execute that file... Genius... except for the fact that when AppleScript compiles this line:
using terms from application "Clean Install:Applications:iWork '09:Keynote.app"
Gets changed to:
using terms from application "Keynote"
Which of course calls the new keynote's dictionary which is empty.
Any thoughts on how to keep applescript from helping me out in this way? (or is there a better plan?)
full code:
using terms from application "Clean Install:Applications:iWork '09:Keynote.app"
--using terms from application "Clean Install:Applications:iWork '09:Keynote.app"
tell application "Clean Install:Applications:iWork '09:Keynote.app"
activate
end tell
end using terms from
many thanks!
I'm flyin' blind here (don't have keynote) ... but have you tried using a pre-defined app string as a variable and raw event codes?
You can use Smile to easily get raw event codes by
making a new script window in Smile;
using the "tell" menu item from the Action menu to make that script window application-specific (no tell
block needed);
write a line of code; select line of code
then use the "Copy translate" menu item (cmd-shift-C)
to copy the raw event codes
pasting that raw event code code into a different window that has your working (normal tell block) script
This is what it looks like when I do this for the Mail app:
set origMail to "MyDrive:Applications:Mail.app"
tell application origMail
delete («class mssg» 1 of «class mbxp» "INBOX" of «class mact» 1)
end tell
( When put in a normal tell block, that line of code would be "delete (message 1 of mailbox "INBOX" of account 1)" )
I haven't tried this but I think it will work... when you compile your code with "using terms from" just place your new version of Keynote in the trash. That should force it to use the old version of Keynote's dictionary and your code should compile. If you then save that code as an "applescript application" then it should work on anybody's computer without need to recompile. NOTE: you may need to restart your computer before this trick would work.
Then you just have the problem of targeting the right application on the user's computer because they too might have both versions. Here's some code to find the path to older versions of Keynote and how you would target that.
set lsregister to "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister"
set appName to "Keynote.app"
set nonapplescriptVersion to "6.0"
-- get the path to all Keynote apps
set appPaths to paragraphs of (do shell script lsregister & " -dump | grep " & quoted form of appName)
-- find the one with a version number less than the nonapplescriptVersion of Keynote
set appPath to missing value
repeat with anApp in appPaths
try
-- extract the path
set AppleScript's text item delimiters to "/"
set tis to text items of anApp
set thisPath to "/" & (items 2 thru end of tis) as text
set AppleScript's text item delimiters to ""
-- check the version
if (version of application thisPath) is less than nonapplescriptVersion then
set appPath to thisPath
exit repeat
end if
end try
end repeat
if appPath is missing value then error "Needed application version not installed."
-- use the older version
using terms from application "Keynote"
tell application appPath
activate
-- do whatever
end tell
end using terms from