Renaming PDFs after the first line


I have imported a few hundred pdf files which all have long numeric names. In all of them the title I would like is the first line of the document. Is there a way of writing a smart rule so that it renames the files after their first line?

Thanks for your help,


Depending on the PDF document the action Change Name using the Proposed Title placeholder should do this.

Great! That’s worked! Out of interest, if I needed to rename after the second or third line, is there a similar way of doing that?


In that case a script is required.

Something like

const record = Application("DEVONthink 3").selectedRevords()[0];
const paragraphs = record.plainText().split('\n');
const secondLine = paragraphs[1];
const thirdLine = paragraphs[2];

Adjust the split depending on the separator you need.

Thanks. I’m just trying the script out. I’ve not used scripts in DT (or anywhere) before. Please can I check if have this set right for renaming after the second line?

Nope. This is JavaScript, not AppleScript. You’re mixing the two, which makes no sense. Since I’m sitting in a train right now, I can’t fix that. You could search for „JavaScript smart rule“ in the forum, that should give you a hint how such a function looks.

Also, please do not post screenshots of code. Post the code included in three backticks like so
code goes here
Screenshots are useless for code. Even more so in dark mode.

Back on the Mac…

Before attempting to put some unknown and untested code into a smart rule to possibly mangle your databases, you should put the script (copy/paste) into Script Editor, set this app’s language selector (upper left) to JavaScript, select a record in DT and then run the script in Script Editor. Use a copy of a record, not the original, to prevent damage.

As you’ll then see, it doesn’t do anything to your record(s), but simply retrieves the 2nd and 3rd line from the selected PDF document, storing them in appropriately named constants. If, for example, you’d want to change the name of your record to the text found in the third line, you’d use = thirdLine;

DO NOT DO THAT without adding some safeguards, checking that thirdLine (or whatever else you come up with) is really what you want the name for your record to be. It could, for example, be a whole paragraph of text, which would make for quite an awkward name.

Now, if you have tested the code, and it does what you want, you can add it to a smart rule. For that to work, you have to set up a scaffolding like this

function onperformsmartrule(records) {
  records.forEach(r => {
     const paragraphs = r.plainText().split('\n');

and add this as internal JavaScript (!) to your smart rule. The name of the function must be onperformsmartrule, everything else is up to you.

You’re not forced to use JavaScript, AppleScript is preferred by many people here (not me, though). You can’t, however, mix the two. tell Application and repeat with etc are all AppleScript constructs that will cause the script compiler to fail and prevent your script from running.

There are a lot of AppleScript and some JavaScript examples floating around in this forum. There’s also my Website on JavaScript for Automation with general information on JavaScript in the AppleVerse and some examples for DT as well as for other apps.

1 Like

Here’s a very simple teaching edition script that lets you pick the paragraph to use as the title…

property defaultPara : 1 -- Default paragraph is the first one
property validTypes : {"txt", "rtf", "rtfd", "markdown", "pdf document", "html", "formatted note"} -- These types should work with the script
property maxChars : 64 -- Used to limit the title length

tell application id "DNtp"
	if not (exists (content record)) then return -- If no file is displayed, quietly stop.
	set sel to (content record)
		if (type of sel as string) is in validTypes then -- Is this a valid filetype?
			set src to plain text of sel -- Get the plain text of the file
			set paracount to (count paragraphs of src) -- Count the paragraphs
			set selectedPara to text returned of (display dialog "What line to use as the title: 1 through " & paracount default answer defaultPara) -- Choose the paragraph
			set textPara to (paragraph selectedPara of src) -- Get the chosen paragraph
			if textPara ≠ "" then -- If the paragraph isn't an empty line…
				if ((count textPara) > maxChars) then set textPara to ((characters 1 thru maxChars of textPara) as string) -- Trim the paragraph to the maximum characters
				set name of sel to textPara -- Set the name of the file to the trimmed paragraph text
			end if
		end if
	on error msg
		display alert msg
	end try
end tell

If the paragraph is an empty line, it does nothing.

Bear in mind the performance depends on the size of the file, e.g., a PDF. I tested with the DEVONthink manual at 300 pages and almost 5800 paragraphs.
There are certainly other approaches that could be taken but this is a pure vanilla AppleScript approach.

1 Like