Regardless of what we think about replacing the slashes with backslashes, this is actually somewhat interesting as a quoting hell issue. One that would come up with other similar constructs.
If your PS1
contains $(echo "\w" | sed 's/\//\\/g')
, what happens is that first Bash processes it for the prompt escapes, like \w
. So echo "\w"
turns into echo "/etc/defaults"
, which basically works for nice pathnames. But at the same time, it also changes the \\
to a single \
... So what you need to get in PS1
, is $(echo "\w" | sed -e 's/\\//\\\\/g')
. Or with double-quotes, the same with more backslashes: $(echo "\w" | sed -e "s/\\\\//\\\\\\\\/g")
.
Then there's the issue of the assignment to PS1
, and there, you're probably going to want a single quoted string, which has to contain single quotes, so you need to replace them with '\''
. It becomes something like this:
PS1='$(echo "\w" | sed -e '\''s/\\//\\\\/g'\'')'
Which is awkward enough that the SE syntax highlighter doesn't seem to follow it correctly, it shows the part between the '\''
s as unquoted.
But... there are better ways of doing that.
The \w
replacement is a bit suspect, since straight text replacement of data on the shell command line is basically an invitation for trouble. If the path was /tmp/quote"me
, a straight replacement would produce echo "/tmp/quote"me"
, with a stray quote. Bash actually does add backslashes to escape the quote, so it becomes echo "/tmp/quote\"me"
, which is ok. But it's still icky, so I'd rather avoid it. There's a very plausible command injection issue looming there if ever the escaping doesn't match the parsing. E.g. the similar echo '\w'
would not work, it'd cause extra backslashes to show up if the path contained any of "$\
, and would completely blow up and be open for various vulnerabilities if it contained a '
. (Similar issues as with SQL injections.)
Also, we can get rid of the quoting hell by defining a function to run that sed
, hiding the s///
command from the prompt itself. Incidentally, we have to use $PWD
here, as the function itself isn't part of the prompt, so \w
won't work:
manglepath() {
echo "$PWD" | sed 's/\//\\/g'
}
PS1='$(manglepath)\$ '
And actually we should be able to use the ${var//pattern/replacement}
expansion instead of calling sed
, and we probably should use printf
instead of echo
:
manglepath() {
printf "%s\n" "${PWD//\//\\}"
}
PS1='$(manglepath)\$ '
PS1="$(echo "\w" | sed 's/\//\\/g')"
with the double quotes tells the shell to run thatecho
+sed
pipeline right there, and to store the result inPS1
. It'll just do the same asPS1='\w'
. You need to escape the$
or put the thing in single quotes to tell the shell to store that command substitution inPS1
. Though you'll get into a bit of an escape hell there. – ilkkachu May 03 '22 at 07:43\etc\defaults
though; you can't use it in that format as input to anything, and everything else will show it with the slashes that actually are there. All you'll get is one thing confusingly showing a different thing from all the others. – ilkkachu May 03 '22 at 07:46/
, not . Unix is not MS Windows, and deceiving yourself that it is will eventually and inevitably result in you making some disastrous mistake when typing in a command. – cas May 03 '22 at 07:46