Hi
i’m trying to set a metadata “kMDItemKeywords” of a pdf file in order to keep an specific information i would like to store.
But impossible to find how to do that with Illustrator when i save the file or via Finder and Acrobat
Any idea will be very helpfull
Regards
Hi,
the simplest way is using exiftool:
property exiftoolPath : "/usr/local/bin/exiftool"
set newMetadataValue to "This is a new metadata"
set imagePath to quoted form of (POSIX path of (choose file of type "pdf"))
-- Add new metadata "Keywords"
do shell script exiftoolPath & " -Keywords=" & quoted form of newMetadataValue & space & imagePath
-- Get all metadata
do shell script exiftoolPath & " -a -u -g1 " & imagePath
Another option to KniazidisR’s perfectly adequate solution.
use framework "Foundation"
use scripting additions
try
set PDFDocumentPath to POSIX path of (choose file with prompt "Select a PDF Document" default location (path to documents folder) of type {"pdf"})
on error
return -- User canceled selecting a PDF Document
end try
set PDFDocumentURL to current application's NSURL's fileURLWithPath:PDFDocumentPath
set PDFDocument to current application's PDFDocument's alloc()'s initWithURL:PDFDocumentURL
set PDFAttributes to current application's NSMutableDictionary's dictionaryWithDictionary:(PDFDocument's documentAttributes())
PDFAttributes's setValue:{"these", "are", "my", "keywords"} forKey:"Keywords"
set PDFDocument's documentAttributes to PDFAttributes
set PDFDocumentSaved to PDFDocument's writeToURL:PDFDocumentURL withOptions:(missing value) -- Could be done more safely
if PDFDocumentSaved then
return "Success"
else
return "Failure"
end if
The way I have saved the modified PDF Document is not the best or safest way to do it.
But only used on this occasion as a simple example.
Regards Mark
Thanks !!
Works fine. I try to adapt to have the same solution for jpg but don’t arrive to do it
Hey Mark,
I tried with kMDItemComment (see: https://developer.apple.com/documentation/coreservices/kmditemcomment?language=objc) by using:
PDFAttributes's setValue:{"mytexthere"} forKey:"Comment"
or using
PDFAttributes's setValue:"mytexthere" forKey:"Comment" -- without the {}
but it didn’t work. Any suggestion?
(I also tried with with kMDItemAuthors, also without success)
Thanks
L.
Apple’s PDFDocument class that I was using does not have a “Comment” attribute.
Thats not to say a PDF Document cannot have a “Comment” attribute, it just means that if your using my technique with the PPDFDocument class, you cannot set one.
Here’s the PDFDocument class’s get and set attributes.
https://developer.apple.com/documentation/pdfkit/pdfdocumentattribute
And here is an example of how you use them.
set PDFDocumentURL to current application's NSURL's fileURLWithPath:PDFDocumentPath
set PDFDocument to current application's PDFDocument's alloc()'s initWithURL:PDFDocumentURL
set myPDFDocAttributes to {Author:"me", CreationDate:missing value, Creator:"me again", Keywords:{"my", "keywords"}, ModDate:missing value, Producer:"also me", Subject:"PDF Doc's", Title:"PDF Doc Attr"}
-- A record containing all the available PDF Document key and value pairs, that you can set to your own values.
-- The CreationDate: and ModDate: keys have to be set to an NSDate class, and the Keywords: key to an array of strings.
-- If you leave the CreationDate: and ModDate: keys as missing value, the Mac's operating system will add the current date.
-- If you leave the Producer: key empty, the Mac's operating system will fill it with it's OS version.
-- If you leave any of the other string values empty, they will not appear in the saved PDF Doc's attributes.
set PDFDocument's documentAttributes to myPDFDocAttributes
Please see the comments I’ve let after the “myPDFDocAttributes” declaration.
These notes are based on my experimentation, but you may find other behaviours with further experiments.
You only have to use the “{}” braces if an array type is required, and “” if a string is required.
So if you wanted to set the CreationDate: or ModDate: attributes, you would do like this
set theDate to current application's NSDate's |date|()
set myPDFDocAttributes to {Author:"", CreationDate:theDate, Creator:"", Keywords:{}, ModDate: theDate, Producer:"", Subject:"", Title:""}
-- OR
PDFAttributes's setValue:theDate forKey:"CreationDate"
Please be aware that the documentation you link to is for Apple’s “Core Services”, which the operating system uses for all file types, certain file types can have certain attributes, but not all of them, it depends on the file type involved.
For example a “txt” file might allow a “Comments” attribute, but a “csv” file might not, I’m not sure myself what attributes are allowed for different file types, so you will have to research that subject.
So in conclusion, if you want to set a “Comment” attribute to a PDF File, and this attribute type is an allowed valid PDF type, then you will have to use KniazidisR’s example to achieve it, and not use the PDFDocument class as in my example, but check first that a “Comment” attribute is a valid attribute for PDF documents.
You could also try opening up various PDF’s sent to you from others, and downloaded off the internet, to see the typical metadata attributes applied to the majority of PDF documents.
You could try this with the first part of my code in my first solution posting like this.
use framework "Foundation"
use scripting additions
try
set PDFDocumentPath to POSIX path of (choose file with prompt "Select a PDF Document" default location (path to documents folder) of type {"pdf"})
on error
return -- User canceled selecting a PDF Document
end try
set PDFDocumentURL to current application's NSURL's fileURLWithPath:PDFDocumentPath
set PDFDocument to current application's PDFDocument's alloc()'s initWithURL:PDFDocumentURL
return (PDFDocument's documentAttributes() as record)
Of the few PDF files that I tried, I have yet to find one with a “Comment” metadata attribute.
Which says a lot about common or valid PDF document metadata attributes.
Regards Mark
Thanks Mark! This is really helpful.
Is there a way to change only one attribute of the list myPDFDocAttributes ?
If I want to leave the title unchanged, Creator unchanged etc… and only “update” the Creator?
I know I could read all this values with ‘mdls’ or with ‘mdimport -t -d2’ , and then fill the list, but if there is a way to re-write only one value will make the process simpler.
Thanks again.
L.
I’m not sure I understand your question really, as the “myPDFDocAttributes” variable is not a AS list, but is an AS record.
So you could change the “Creator” key value like you would with any other AppleScript record key value.
set myPDFDocAttributes to {Author:"", CreationDate:missing value, Creator:"", Keywords:{}, ModDate:missing value, Producer:"", Subject:"", Title:""}
set Creator of myPDFDocAttributes to "Mark FX"
return myPDFDocAttributes
AppleScript records are the equivalent of an NSDictionary, although AS records are not as versatile as the Dictionary, but you can coerce back and forward between them.
If you want to check or loop through the keys of a PDF document attributes dictionary, then simply use conditionals or a repeat loop.
use framework "Foundation"
use scripting additions
try
set PDFDocumentPath to POSIX path of (choose file with prompt "Select a PDF Document" default location (path to documents folder) of type {"pdf"})
on error
return -- User canceled selecting a PDF Document
end try
set PDFDocumentURL to current application's NSURL's fileURLWithPath:PDFDocumentPath
set PDFDocument to current application's PDFDocument's alloc()'s initWithURL:PDFDocumentURL
set PDFAttributes to current application's NSMutableDictionary's dictionaryWithDictionary:(PDFDocument's documentAttributes()) -- This is a mutable NSDictionary
set PDFAttributeKeys to PDFAttributes's allKeys() as list -- Returns all of the keys
repeat with attribute in PDFAttributeKeys
log attribute
end repeat
-- OR
if PDFAttributeKeys contains "Creator" then
return true
else
return false
end if
It does not matter if the “Creator:” key is in the PDF document attributes dictionary / record.
PDFAttributes's setValue:"Mark FX" forKey:"Creator"
Because the above will change it’s value if it exists, or add it to the dictionary / record if it does not.
I would recommend you read up on the NSDictionary class to learn more about working with the contained keys and values.
As you can also change and modify multiple key and value pairs simultaneously, which is not possible with AppleScript records.
Hope that helps
Regards Mark
Thanks Mark. Indeed I intended to say “record” and not “list”. I always think the the “record” is a sub-type of “list” … which maybe it is … Anyway. Thanks a lot !
I also realized that in your script that you first import all attributes with the command into a record:
set PDFAttributes to current application's NSMutableDictionary's dictionaryWithDictionary:(PDFDocument's documentAttributes())
and then change one (or more), with:
PDFAttributes's setValue:"Mark FX" forKey:"Creator"
consolidate the changes:
set PDFDocument's documentAttributes to PDFAttributes
finally save the changes.
set PDFDocumentSaved to PDFDocument's writeToURL:PDFDocumentURL withOptions:(missing value)
I have it clear now. At least it worked …
Thanks again.
L
Hi ldicroce
I’m pleased it all made sense to you in the end, as it can be confusing when mixing AppleScript code and class types, in the same code as AppleScriptObjC using Cocoa framework class types.
As powerful and welcomed as the AppleScriptObjC bridge is, it can make for unreadable code on occasions, and sometimes means reading Apple’s developer documentation to understand the framework classes, and how to use them.
But understanding that certain AppleScript class types are interchangeable with Foundation framework class types is necessary.
AppleScript list’s are interchangeable with NSArray’s, and AppleScript record’s are interchangeable with NSDictionary’s, although unlike AppleScript list’s and record’s which are editable, to make an NSArray and NSDictionary editable, you have to use the mutable types, NSMutableArray and NSMutableDictionary respectively.
Good luck with it.
Regards Mark