Escaping both forward slash and back slash with sed

You need to escape (with backslash \) all substituted slashes / and all backslashes \ separately, so:

$ echo "/tmp/test/folder1/test.txt" | sed 's/\//\\\//g'
\/tmp\/test\/folder1\/test.txt

but that's rather unreadable.

However, sed allows to use almost any character as a separator instead of /, this is especially useful when one wants to substitute slash / itself, as in your case, so using for example semicolon ; as separator the command would become simpler:

echo "/tmp/test/folder1/test.txt" | sed 's;/;\\/;g'

Other cases:

  • If one wants to stick with slash as a separator and use double quotes then all escaped backslashes have to be escaped one more time to preserve their literal values:

    echo "/tmp/test/folder1/test.txt" | sed "s/\//\\\\\//g"
    
  • if one doesn't want quotes at all then yet another backslash is needed:

    echo "/tmp/test/folder1/test.txt" | sed s/\\//\\\\\\//g
    

Or, if the value is in a (bash) shell variable:

var=/tmp/test/folder1/test.txt
$ echo "${var//\//\\\/}"
\/tmp\/test\/folder1\/test.txt

The first // start parameter expansion, saying to replace all matches with the replacement. The next \/ is the escaped / to match, and the \\\/ is an escaped \ followed by an escaped / as the replacement.


The final solution will be this one:

$ sed 's:/:\\/:g'  <<<"$str"
\/tmp\/test\/folder1\/test.txt

But to explain how to get there:
Yes, you were missing one backslash:

$ str='/tmp/test/folder1/test.txt'
$ sed "s/\//\\\\\//g" <<<"$str"
\/tmp\/test\/folder1\/test.txt

I hope that one space will make it clear:

$ sed "s/\//\\\\ \//g"  <<<"$str"
\ /tmp\ /test\ /folder1\ /test.txt

But, if you were to change the sed delimiter to : (for example):

$  sed "s:\/:\\\\\/:g"  <<<"$str"
\/tmp\/test\/folder1\/test.txt

But that is not strictly correct as the (now not special) / does not need scaping:

$ sed "s:/:\\\\/:g"  <<<"$str"
\/tmp\/test\/folder1\/test.txt

And, if you were to use single quotes instead of double quotes the shell will not change double \\ to one, so less \ will be correct:

$ sed 's:/:\\/:g'  <<<"$str"
\/tmp\/test\/folder1\/test.txt

Which is quite cleaner.

Tags:

Bash

Sed