Search code examples
rubypathtilde-expansion

Collapsing home folder in path to tilde character


In Swift, abbreviatingWithTildeInPath creates “a new string that replaces the current home directory portion of the current path with a tilde (~) character”. In other words, it turns /Users/username/Desktop/ into ~/Desktop.

In Ruby we can do the reverse with File.expand_path:

File.expand_path('~/Desktop')
# => /Users/username/Desktop/

But there’s seemingly no native way to abbreviate a path with a tilde. I’m achieving it with:

'/Users/username/Desktop/'.sub(/^#{ENV['HOME']}/, '~')

That seems to work reliably, but are there any flaws I’m missing? Or better yet, is there a native method?


Solution

  • There are several subtle issues with your approach

    1. Dir.home is a more reliable way to get the home directory in case the script is running a weird environment
    2. home directory names can contain regex special characters, namely ., which might cause false positives in a regex. Fixed with Regexp.escape
    3. the path may be only the home directory with no trailing slash. Fixed with a positive lookahead for the end of the string or a separator
    4. windows paths might use backslashes. Fixed with File::SEPARATOR
    5. Ruby regexs are multiline, in which case ^ and $ will find the first line that matches, not just the start of the string. Fixed with \A and \Z, though realistically you should never be passing multiline strings to this method
    def File.collapse_path path
      path.sub /\A#{Regexp.escape Dir.home}(?=\Z|#{File::SEPARATOR})/, ?~
    end