Shell Tricks: convert file urls to UNIX paths

Today’s shell trick is for converting file:// urls into valid shell paths. This isn’t a terribly common scenario, but I occasionally work with tools, especially in GUI applications, that output file urls and need to change something like:

file:///Users/ttscoff/Desktop/my%20file.txt

into:

~/Desktop/my\ file.txt

These are Bash-specific, due mostly to some variable mangling syntax, but could easily be converted for zsh and others.

I handle shell escaping with the default Ruby Shellwords module. It’s fast and covers edge cases, avoiding a lot of sed/awk work. There are modules in other scripting languages as well, but Ruby and the Shellwords module are standard on all OS X systems (and what I know best). Substitute based on your personal preference.

# Ruby ShellWords escapeshellesc(){local output
# If any arguments are passed to the function, assume that's the inputif[[$# == 0 ]]; thenoutput=$(ruby -e 'require "shellwords"; puts Shellwords.escape(STDIN.read.strip)')# otherwise, take input from STDIN so it can be used in piped commandselseoutput=$(ruby -e 'require "shellwords"; puts Shellwords.escape(ARGV.join(" ").strip)'$@)fiecho"$output"}

I also use Ruby (CGI class methods) to unescape urls when working in the shell. It will convert any percent-encoded entities to their natural state:

Lastly, a quick utility using sed to replace full paths in home directory with a tilde (~), e.g. /Users/ttscoff/Desktop becomes ~/Desktop. It’s more readable and allows more portability as the tilde will expand to whatever the current user’s home folder is.

Note: When input is recieved from STDIN instead of arguments, it automatically calls the shell escape function to avoid losing existing escaping through the read command. Thus a call to shellesc | shorthome in other functions is redundant (though not fatal).

Lastly, here’s the function that combines the previous utility functions to convert a file:// url to a shell-escaped path.

If you pass -c as the first argument (or only argument if you want to use piped input from STDIN), results are copied to the clipboard (using pbcopy, which is OS X-only). The bulk of the function is a simple piped chain of the above functions, with a quick variable mangling in Bash to remove the file:// prefix.

With that code sourced in your ~/.bash_profile, you can use commands such as echo "file:///Users/ttscoff/Desktop/my%20file.md" | url2path or url2path file:///Users/ttscoff/Desktop/my%20file.md to get the filepath, either directly or as part of another script.

The command (usable as an alias) pbpaste | url2path -c will convert a url in the clipboard into a file path, in place, ready for pasting.