5

I am a typographer working with many fonts that have incorrect or incomplete filenames. I am on a Mac and have been using Hazel, AppleScript, and Automator workflows, attempting to automate renaming these files*. I require a script to replace the existing filename of ttf, woff, or woff2 files in Finder with the font's postscriptName. I know of tools (fc-scan/fontconfig, TTX, etc) which can retrieve the PostScript name-values I require, but lack the programming knowhow to code a script for my purposes. I've only managed to setup a watched directory that can run a script when any files matching certain parameters are added.

*To clarify, I am talking about changing the filename only, not the actual names stored within the font. Also I am open to a script of any compatible language or workflow of scripts if possible, e.g. this post references embedding AppleScript within Shell scripts via osascript.

StackExchange Posts I've Consulted:
How to get Fontname from OTF or TTF File?
How to get PostScript name of TTF font in OS X?
How to Change Name of Font?
Automate Renaming Files in macOS

Others:
https://github.com/dtinth/JXA-Cookbook/wiki/Using-JavaScript-for-Automation
https://github.com/fonttools/fonttools
https://github.com/devongovett/fontkit
https://www.npmjs.com/package/rename-js
https://opentype.js.org/font-inspector.html
http://www.fontgeek.net/blog/?p=343
https://www.lantean.co/osx-renaming-fonts-for-free

Edit: Added the following by request.
1) Screenshot of a somewhat typical webfont, illustrating how the form fields for font family and style names are often incomplete, blank, or contain illegal characters.
2) The woff file depicted (also, as base64). Screenshot Thank you all in advance!

Moscarda
  • 333
  • 2
  • 14
  • Before we go down a rabbit hole... what on earth are you doing that requires renaming files? Almost every possible technology I know of will read the font family name from the *actual OpenType metadata*, not the file name (which would be **incredibly wrong** for a parser to do) so based on what I know about the OpenType spec, and OpenType fonts, there is literally no reason to do this. Can you explain what's going on here? – Mike 'Pomax' Kamermans May 29 '17 at 23:52
  • Yes if installed, most fonts names would display correctly regardless of filenames. But that would require time installing and inspecting said files, and it wouldn't help organising my filesystem. Also with webfonts, font family and/or style names are often missing, but the PostScript names are intact which is why I am going for that info. I know I could run the fonts in question through a converter that would output new files with more accurate names, but much can go wrong or get lost in conversion. – Moscarda May 30 '17 at 02:19
  • Not really, if you have to work with lots of fonts you use a font manager, rather than whatever crappy font management the OS offers. This lets you bulk-inspect, selectively install, etc. fonts without ever having the OS do its silly things (like "having to put them in a C:\Windows\Fonts dir" etc). As for "running through a converter", actually *very little* can go wrong with the right tool. You want [TTX](https://github.com/fonttools/fonttools), which does proper round tripping and is rather tailored to doing something like bulk-copying postscript names into the name table as family string id – Mike 'Pomax' Kamermans May 30 '17 at 03:54
  • yeah I have heard of TTX, is there a way I could use it to automate the naming of the files themselves? I can appreciate that you might not understand the need for such a workflow, but it would greatly help me. – Moscarda May 30 '17 at 13:51
  • yeah it's a python based application, you can just write a bit more python that uses TTX as library call to convert a font to xml, updates the name table with a basic XML parser, and then converts the xml back to font based on the found postscript name. – Mike 'Pomax' Kamermans May 30 '17 at 18:13
  • While I've dabbled a bit with coding, I am by no means a programmer. I don't expect anyone here to do all the work for me, but could you point me in the right direction to get me started? I'm vaguely familiar with Python and XML, and I get the purpose of TTX, but I haven't a clue as to how to combine them into a single script. I'm sure its simple for a programmer and I _want to learn_ but I'm definitely more a creative than a coder. **Any and all help is greatly appreciated!** – Moscarda May 30 '17 at 21:30
  • I don't have good advice there, other than "just start by the basic tutorials on Python all over the web, and asking for help specific on the fonttools issue tracker to ask on how to use it in a larger script". The main body of work when it comes to automation, and that's what you're trying to do, is writing (=programming) the script that will do the automation for you, no two ways about it. Start by just using TTX and see what it generates, then try to write a tiny script that simply reads that resulting file in, then see if you can make it "change" values, then see if you can write that, etc – Mike 'Pomax' Kamermans May 30 '17 at 23:41

1 Answers1

5

Since you mentioned Automator in your question, I thought I'd try and solve this while using that to rename the file, along with standard Mac bash to get the font name. Hopefully, it beats learning a whole programming language.

I don't know what your workflow is so I'll leave any deviations to you but here is a method to select a font file and from Services, rename the file to the font's postscript name… based on Apple's metadata, specifically "com_apple_ats_name_postscript". This is one of the pieces of data retrieved using 'mdls' from the Terminal on the font file. To focus on the postscript name, grep the output for name_postscript. For simplicity here, I'll exclude the path to the selected file.

Font Name Aquisition

So… running this command…

mdls GenBkBasBI.ttf | grep -A1 name_postscript

… generates this output, which contains FontBook's Postscript name. The 'A1' in grep returns the found line and the first line after, which is the one containing the actual font name.

com_apple_ats_name_postscript  = (
    "GentiumBookBasic-BoldItalic"

Clean this up with some more bash (tr, tail)…

tr -d \  | tail -n 1 | tr -d \"

In order, these strip spaces, all lines excepting the last, and quotation marks. So for the first 'tr' instance, there is an extra space after the backslash.

In a single line, it looks like this…

mdls GenBkBasBI.ttf | grep -A1 name_postscript | tr -d \  | tail -n 1 | tr -d \" 

…and produces this…

GentiumBookBasic-BoldItalic

Now, here is the workflow that includes the above bash command. I got the idea for variable usage from the answer to this question…

Apple Automator “New PDF from Images” maintaining same filename

Automator Workflow

Automator Workflow screenshot

At the top; Service receives selected 'files or folders' in 'Finder'.

  1. Get Selected Finder Items

This (or Get Specified…) is there to allow testing. It is obviated by using this as a Service.

  1. Set Value of Variable (File)

This is to remember which file you want to rename

  1. Run Shell Script

This is where we use the bash stuff. The $f is the selected/specified file. I'm running 'zsh' for whatever reason. You can set it to whatever you're running, presumably 'bash'.

  1. Set Value of Variable (Text)

Assign the bash output to a variable. This will be used by the last action for the new filename.

  1. Get Value of Variable (File)

Recall the specified/selected file to rename.

  1. Rename Finder Items: Name Single Item

I have it set to 'Basename only' so it will leave the extension alone. Enter the 'Text' variable from action 4 in here.

Mockman
  • 292
  • 2
  • 8
  • Wow, this sounds great... a few questions though... 1) You mention FontBook: is it not possible to change the name before installing the fonts? I'd rather not use FontBook in my workflow, unless it can't be avoided, 2) A few years ago I tried `zsh` but quickly switched back to `bash` when I discovered the formatting differences between the two that could cause some scripts to throw errors if not accounted for. Are you saying that the difference shouldn't matter in this instance? 3) Would you mind upload the finalised Workflow/Service you created while testing your answer? Cheers! – Moscarda Jun 05 '17 at 05:59
  • Font Book isn't part of the workflow. I only mentioned it to show that the output from the mdls command is consistent with it. There isn't any 'installing' to do. The bash/zsh part is a one-liner. I can't imagine it making a difference. But you can always just run the command yourself to confirm that it generates the correct output. I don't think I can upload anything with a reputation of 1. Not even the screenshot :) So you're on your own from this point. But it shouldn't take more than two minutes to re-create the Service. Cheers. – Mockman Jun 05 '17 at 14:20
  • This works great for your ttf example, but as stated above: it is the webfonts that often have missing or incorrect family/style names. Hence the postscript values being of such importance. It's fine if the workflow for each font-filetype has to be a little different, but I really need the ability to do the same for woff/woff2 files as you've done with ttf. Cheers! – Moscarda Jun 09 '17 at 20:23
  • The information has to be stored somewhere within the file. Otherwise, you'd basically need a font recognition app. But if any of the other metadata fields contained the correct value, it could be extracted similarly. – Mockman Jun 12 '17 at 00:47
  • I upvoted your answer, but if you wouldn't mind offering some woff/woff2-specific help, I'll gladly award you the 50 point bounty. I did try variations on what you posted for ttf value-extraction, but had no luck. I am positive the information is there: if I open the fonts in an editor like FontLab, the PostScript names are almost always intact, sometimes the font name is even visible just by selecting "Get Info" in the Finder. But I'm trying to avoid doing this manually given the countless number of fonts I work with. – Moscarda Jun 12 '17 at 07:02
  • I've been scouring repos for applicable webfont scripts, trying to do my part while it is obvious I haven't a clue how to test or deploy my findings... which include an `npm` parser for [woff](https://github.com/andyjansson/woff-parser) _and_ [woff2](https://github.com/andyjansson/woff2-parser), and also this [php-font-lib](https://github.com/PhenX/php-font-lib) that might work?. I think I understand enough to know that one of these could be used to accomplish what I need, but I can't do it alone. Please help! – Moscarda Jun 12 '17 at 08:52
  • What is the name of the field though? Can you point me to an example webfont somewhere, and the applicable name? – Mockman Jun 13 '17 at 00:36
  • I can't believe I forgot about this. I will upload an image and an example. Many but not all of the problematic webfonts are commercial fonts, which could explain missing info—these do not require much of the info that desktop fonts do. But to be clear, I am only trying to organise fonts in my possession which I have purchased myself or for a client. I'd never modify or reverse engineer anything that would violate its EULA. – Moscarda Sep 02 '17 at 06:58
  • here is a link to the actual file, I didn't realise one couldn't add them directly. [woff](https://github.com/enonce/enonces/blob/master/docs/%C3%B8.woff?raw=true) – Moscarda Sep 02 '17 at 07:48