ZSH: Escape or quote a string with backslashes

10.8k Views Asked by At

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
4

There are 4 best solutions below

0
On BEST ANSWER

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//\\//}"
}
1
On

Just escape each backslash with another backslash:

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

0
On

You don't need parsewinpath at all. Just use parameter expansion to replace backslashes with forward slashes.

openwinpath /Volumes/myvolume${1//\\//}
0
On

Sorry, I know I'm 5 years late, but I thought an explanation of the problem's root and a workaround might be worth it for anyone else who ends up here:

Bash has a certain syntax. It interprets backslashes in a certain way. So you can't paste text with backslashes into the Terminal.

However, if you've copied the text to the clipboard, you may be able to circumvent bash's syntax by using a shell command to read the clipboard inside your script. So instead of using $1 to get your path from your script's argument, use pbpaste to read the clipboard directly.