Search code examples
macoszshoh-my-zshzshrc

ZSH: Escape or quote a string with backslashes


I wrote a little function, that "translates" a Windows path to a OSX path and opens it in the Finder. The function works perfectly with bash, but not with zsh (I use oh-my-zsh).

The problem is that it parses specific backslash combinations, for instance: \f, \a, \01, \02, \03, etc...

For example, this path string is the input:

"\60_Project\6038_Projekt_Part\05_development\assets\img\facebook"

After the translation function, the \f sequence (from img\facebook) is incorrectly translated as whitespace, producing the output:

"/60_Project/6038_Project_Part_developmentssets/img
                                                                                   acebook"

My goal is to just paste in a Windows path and not have to manually change anything.

How can I escape or quote a string with zsh, to get the result I want?

Here is the code I wrote:

function parsewinpath {
  echo $1 | sed -e 's/\\/\//g'
}

function openwinpath {
  echo "Opening..."
  open $(parsewinpath "/Volumes/myvolume$1")
}

Usage:

openwinpath '\60_Project\6038_Project_Part\05_development\assets\img\facebook'

The result should be that the Finder opens:

/Volumes/myvolume/60_Project/6038_Project_Part/05_development/assets/img/facebook

Solution

  • The problem is that echo is trying to interpret escape sequences in the string as it prints it. Some versions of echo do this; some do it only if you pass the -e option; some print "-e" as part of their output; some do ... other random things. Basically, if you give echo something that contains escapes and/or starts with "-", there's no telling what it'll do.

    Option 1: Use printf instead. It's a little more complicated, because you have to give it a format string as well as the actual string to be printed, but it's much more predictable. Oh, and double-quote variable references:

    function parsewinpath {
      printf '%s\n' "$1" | sed -e 's/\\/\//g'
    }
    

    Option 2: As @chepner pointed out, you can just skip echo, sed, and the whole mess, and use a parameter expansion to do the job:

    function openwinpath {
      echo "Opening..."
      open "/Volumes/myvolume${1//\\//}"
    }