Windows PATH to posix path conversion in bash

2019-01-17 03:22发布

问题:

How can I convert a Windows dir path (say c:/libs/Qt-static) to the correct POSIX dir path (/c/libs/Qt-static) by means of standard msys features? And vice versa?

回答1:

I don't know msys, but a quick google search showed me that it includes the sed utility. So, assuming it works similar in msys than it does on native Linux, here's one way how to do it:

From Windows to POSIX

You'll have to replace all backslashes with slashes, remove the first colon after the drive letter, and add a slash at the beginning:

echo "/$pth" | sed 's/\\/\//g' | sed 's/://'

or, as noted by xaizek,

echo "/$pth" | sed -e 's/\\/\//g' -e 's/://'

From POSIX to Windows

You'll have to add a semi-colon, remove the first slash and replace all slashes with backslashes:

echo "$pth" | sed 's/^\///' | sed 's/\//\\/g' | sed 's/^./\0:/'

or more efficiently,

echo "$pth" | sed -e 's/^\///' -e 's/\//\\/g' -e 's/^./\0:/'

where $pth is a variable storing the Windows or POSIX path, respectively.



回答2:

Are you using it on cygwin? If yes, then there is a readymade utility called cygpath.exe in cygwin package just for doing that.

Output type options:
  -d, --dos             print DOS (short) form of NAMEs (C:\PROGRA~1\)
  -m, --mixed           like --windows, but with regular slashes (C:/WINNT)
  -M, --mode            report on mode of file (binmode or textmode)
  -u, --unix            (default) print Unix form of NAMEs (/cygdrive/c/winnt)
  -w, --windows         print Windows form of NAMEs (C:\WINNT)
  -t, --type TYPE       print TYPE form: 'dos', 'mixed', 'unix', or 'windows'


回答3:

Here is my implementation (tested on git bash).

From POSIX to Windows

sed '
    \,/$, !s,$,/,
    \,^/, s,/,:/,2
    s,^/,,
    s,/,\\,g
    ' <<< "$@"

Works for:

/c/git
relative/dir
c:/git
~
.
..
/c
/c/
./relative/dir
/sd0/some/dir/

except

/
<path with space>

Explanation:

\,^/, s,/,:/,2 (converts /drive/dir/ to /drive:/dir/) is the heart of it and inserts : before the 2nd /. I use , for delim instead of / for readability. If starting with / (\,^/,), then replace / with :/ for the 2nd occurrence. I do not want to assume drive letter length of 1 so this works for /sd0/some/dir.

s,^/,, removes the leading / and s,/,\\,g converts all / to \.

\,/$, !s,$,/, is to handle the corner case of /c and ensure 2nd / (/c/) for the next command to work.

Note:

If here string <<< does not work in your shell then you can echo and pipe as

echo "$@" | sed ...

Errata

Here e script