The Problem ¶
My workflow for naming files has never been anything to write home about. Squarespace had a nifty ‘auto-create-a-URL-slug’ feature that I sorely missed after transitioning to Camel. For the past month, I had been doing it by hand. And frankly, it was just long and tedious as you can imagine.
For instance, suppose I wanted to create the filename (and in Camel, the resultant URL slug) for this post:
Easily Create Filenames & URL Slugs From Blog Post Titles
It isn’t the longest I’ve ever dreamt up, but it certainly isn’t the shortest, either. If I wanted to create a URL-friendly filename, it would take several steps.
- First, I would select and copy the title’s text
- Next,
Command-S
to invoke the save dialog box - Then I paste the previously selected text into the Save As field:
- After that, I start manually changing the uppercase letters to lowercase, removing spaces and replacing them with hyphens, and deleting URL-unfriendly characters like
&
:
There had to be a better way.
The Solution ¶
I tried a few browser searches, but nothing came up. I decided it would be a good idea to ask the king of scripting (at least amongst my Twitter follow’s):
@ToniWonKanobi I wrote a Python function that does that as part of a blog-posting script. You could build a script/service from it.
— Dr. Drang (@drdrang) June 27, 2015
The good doctor was kind enough to send me an email with the contents of a Python script.
On June 27, 2015 at 8:34:20 AM, Dr. Drang (drdrang@gmail.com) wrote:
This takes the title as standard input and returns the hyphen-separated slug on standard output. You’ll need to install the unidecode library.
#!/usr/bin/env python # coding: utf8 from sys import stdin, stdout from unidecode import unidecode from datetime import datetime import re def slugify(u): "Convert Unicode string into blog slug." u = re.sub(u'[–—…/:;,.]', '-', u) # replace separating punctuation a = unidecode(u).lower() # best ASCII substitutions, lowercased a = re.sub(r'[^a-z0-9 -]', '', a) # delete any other characters a = a.replace(' ', '-') # spaces to hyphens a = re.sub(r'-+', '-', a) # condense repeated hyphens a = a.strip('-') # delete leading and trailing hyphens return a title = stdin.read().strip() slug = slugify(title.decode('utf8')) stdout.write(slug)
Regards, Dr. Drang
I tried getting it to work, but, alas, it was beyond my understanding.
Brett Terpstra’s suggestion ended up being the winner:
@ToniWonKanobi tons. Look up "slugify".
— Brett Terpstra (@ttscoff) June 27, 2015
Ah. Slugify. I went back and double-checked Dr. Drang’s script. It was basically leveraging Slugify.
After a bit more searching, I found this page, in which Alex Plumb shared his AppleScript, cribbed from two other AppleScripts he found elsewhere online.
After some cribbing of my own, here is the contents of my version of Alex’s script:
# What is this?
# This AppleScript takes as input the clipboard content [that is potentially unsafe-for-URLs string of text] (such as a blog post in Title Case)
# The script then creates a URL-safe version
# For example: `This Is a Title of a Post!` --> `this-is-a-title-of-a-post`
# Boomshakalaka
# This is from https://superuser.com/questions/635351/process-clipboard-content-on-mac-os
# The workflow:
# 1) Select text
# 2) Copy to clipboard
# 3) Run Slugify.workflow (as a Service in macOS `~/Library/Services`)
# 4) Paste converted text
set theclip to the clipboard contents
on normalize(the_string)
set p_script to ¬
"# -*- coding: utf-8 -*-
import unicodedata, sys
def normalize(x):
normal_form_1 = 'NFKD'
normal_form_2 = 'NFC'
x = unicodedata.normalize(normal_form_2, x)
x = x.lower()
x = x.replace(u'ß', u'ss')
x = x.replace(u'å', u'aa')
x = unicodedata.normalize(normal_form_1, x)
x = u''.join([c for c in x if not unicodedata.combining(c)])
x = x.encode('utf-8')
return x
arg = sys.argv[1].decode('utf-8')
x = normalize(arg)
print x"
set p_script to quoted form of p_script
set the_string to quoted form of the_string
return (do shell script ("python -c " & p_script & " " & the_string))
end normalize
on change_case(this_text)
set the comparison_string to "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
set the source_string to "abcdefghijklmnopqrstuvwxyz"
set the new_text to ""
repeat with this_char in this_text
set x to the offset of this_char in the comparison_string
if x is not 0 then
set the new_text to (the new_text & character x of the source_string) as string
else
set the new_text to (the new_text & this_char) as string
end if
end repeat
return the new_text
end change_case
on replace_chars(this_text, search_string, replacement_string)
set AppleScript's text item delimiters to the search_string
set the item_list to every text item of this_text
set AppleScript's text item delimiters to the replacement_string
set this_text to the item_list as string
set AppleScript's text item delimiters to ""
return this_text
end replace_chars
# Alex had a bunch of special characters getting converted to their URL-safe versions. Since my desire was to just create clean filenames, I actually wanted to remove those characters entirely
set theresult to normalize(theclip)
set theresult to replace_chars(theresult, " ", "-")
set theresult to change_case(theresult)
set theresult to replace_chars(theresult, "%", "")
set theresult to replace_chars(theresult, "<", "")
set theresult to replace_chars(theresult, ">", "")
set theresult to replace_chars(theresult, "#", "")
set theresult to replace_chars(theresult, "{", "")
set theresult to replace_chars(theresult, "}", "")
set theresult to replace_chars(theresult, "|", "")
set theresult to replace_chars(theresult, "\\", "")
set theresult to replace_chars(theresult, "^", "")
set theresult to replace_chars(theresult, "~", "")
set theresult to replace_chars(theresult, "[", "")
set theresult to replace_chars(theresult, "]", "")
set theresult to replace_chars(theresult, "`", "")
set theresult to replace_chars(theresult, ";", "")
set theresult to replace_chars(theresult, "/", "")
set theresult to replace_chars(theresult, "?", "")
set theresult to replace_chars(theresult, ":", "")
set theresult to replace_chars(theresult, "@", "")
set theresult to replace_chars(theresult, "=", "")
set theresult to replace_chars(theresult, "&", "")
set theresult to replace_chars(theresult, "$", "")
# I added the following three replacements
set theresult to replace_chars(theresult, ",", "")
set theresult to replace_chars(theresult, "'", "")
set theresult to replace_chars(theresult, "\"", "")
And here’s a screenshot of the workflow:

Explanation ¶
Essentially, what my Slugify.workflow
does is take selected text and automate the changes I was making to the title text previously. It makes uppercase letters lowercase, and it removes spaces and funky characters and replaces them with hyphens.
I also assigned a keyboard shortcut to the service, so that I don’t have to invoke the ‘right-click’ submenu.
This couldn’t get any easier.
Source ¶
You can check out my Slugify.applescript
on GitHub. There are instructions there for creating an Automator service as well.