Windows PATH to posix path conversion in bash
Asked Answered
O

8

75

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?

Occlusive answered 4/12, 2012 at 10:50 Comment(0)
B
54

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.

Boozy answered 4/12, 2012 at 11:6 Comment(11)
@Dukales I can't test this, so does this work? If not, what are the error messages?Boozy
In Windows to POSIX leading slash is superfluous.Occlusive
@Dukales: ...why? AFAIK, without the leading slash it indicates a relative path, wheras the leading slash makes it an absolute path w.r.t. the filesystem rootBoozy
I mean that the $PATH is the standard envvar.Occlusive
@Dukales: ah, like so. That is entirely true. I intended $PATH to be a user-defined variable; I'll edit.Boozy
You know, there is no need to pipe several invocations of sed, just pass multiple -e command arguments to single instance (like sed -e one -e two).Orgulous
when using the bash shipped with git, the drive letter needs to be lowercased, and some folder names may begin with a '$' - try this: echo "$pth" | sed -e 's#\\#/#g' -e 's#\$#/\\$#g' -e 's#^\([a-zA-Z]\):#/\L\1#Tiltyard
When converting a strings with multiple paths from Windows to POSIX, a leading / has to be added to every path. The more effiicient command version will become: echo "$pth" | sed -e 's/\\/\//g' -e 's/\([a-zA-Z]\):/\/\1/g'Retiarius
@Tiltyard Perhaps case is irrelevant now. My version of bash GNU bash, version 4.3.42(3)-release (x86_64-pc-msys) with git 2.6.3.windows.1 accepts /C or /c as equivalent.Hailstone
In Git Bash (at least; I don't know how Cygwin or other POSIX compatible shells in Windows treat Windows paths), the path prefix X: (where X is the driver letter) becomes /x, so sed 's/://' should be changed to sed -r 's|^([^:]+):|\/\L\1|' (at least when used in Git Bash; I also took the liberty to change / to | as I personally find this much less confusing in sed scripts).Zola
This assumes C: is mounted on /c etc. which is not necessarily the case (true for git-bash, false for cygwin)Unbreathed
A
79

Cygwin, Git Bash, and MSYS2 have a readymade utility called cygpath.exe 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'
Anemography answered 4/12, 2012 at 12:16 Comment(11)
Have a look at this mail: sourceforge.net/mailarchive/message.php?msg_id=8686481Anemography
Whoever has downvoted this answer, please also comment about any mistake, so that I could rectify... :-)Anemography
cygpath appears to work on MINGW64 (git bash). Not sure if it's because I have cygwin installed as well or has been added since this question - but I got the expected outcome from cygpath 'd:\something' - how could it automatically translate a string from the clipboard or custom environment variable?Cattycornered
@hood: "Not sure if it's because I have cygwin installed as well" yes, that's the likely explanation... "how could it automatically translate a string from the clipboard or custom environment variable" Not sure what is expected here.Anemography
Only small caveat, the utility only converts any path string, does not check to see the path exists.Mathian
@SGM1: I think, that's good/intentional. e.g. you may want to do this: mkdir C:\temp\new_dir So, you would do mkdir /cygdrive/c/temp/new_dir, using cygpath to convert the paths. If cygpath had been checking the existence of the target, you would not be able to convert such paths...Anemography
sooo anoying when utilities don't support -- from std in pwd | cygpath -w -- is preferrable over to cygpath -w $(pwd) <sigh/>Disobey
cygpath.exe comes included when you install git-bash. You don't need to have cygwin or even know what cygwin is. It's in path when you're using git-bashUshas
@ZYinMD, But then you need to install git-bash. I don't have to install git if I don't need to. Basically, many softwares are cygwin based (like git-bash) and ship a minimal version of cygwin. You can use whatever you have. I have been using cygwin for a long time without having or even knowing git-bash. cygpath.exe comes installed with cygwin.Anemography
Yes @anishsane, I should've have worded my comment differently. What I meant was "btw if you (the reader) have already installed git-bash (many do, in 2020), then you already have cygpath in path, without needing to know what cgwin is.Ushas
Thank you... :-) On an unrelated note, I have moved from cygwin to WSL2.Anemography
B
54

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.

Boozy answered 4/12, 2012 at 11:6 Comment(11)
@Dukales I can't test this, so does this work? If not, what are the error messages?Boozy
In Windows to POSIX leading slash is superfluous.Occlusive
@Dukales: ...why? AFAIK, without the leading slash it indicates a relative path, wheras the leading slash makes it an absolute path w.r.t. the filesystem rootBoozy
I mean that the $PATH is the standard envvar.Occlusive
@Dukales: ah, like so. That is entirely true. I intended $PATH to be a user-defined variable; I'll edit.Boozy
You know, there is no need to pipe several invocations of sed, just pass multiple -e command arguments to single instance (like sed -e one -e two).Orgulous
when using the bash shipped with git, the drive letter needs to be lowercased, and some folder names may begin with a '$' - try this: echo "$pth" | sed -e 's#\\#/#g' -e 's#\$#/\\$#g' -e 's#^\([a-zA-Z]\):#/\L\1#Tiltyard
When converting a strings with multiple paths from Windows to POSIX, a leading / has to be added to every path. The more effiicient command version will become: echo "$pth" | sed -e 's/\\/\//g' -e 's/\([a-zA-Z]\):/\/\1/g'Retiarius
@Tiltyard Perhaps case is irrelevant now. My version of bash GNU bash, version 4.3.42(3)-release (x86_64-pc-msys) with git 2.6.3.windows.1 accepts /C or /c as equivalent.Hailstone
In Git Bash (at least; I don't know how Cygwin or other POSIX compatible shells in Windows treat Windows paths), the path prefix X: (where X is the driver letter) becomes /x, so sed 's/://' should be changed to sed -r 's|^([^:]+):|\/\L\1|' (at least when used in Git Bash; I also took the liberty to change / to | as I personally find this much less confusing in sed scripts).Zola
This assumes C: is mounted on /c etc. which is not necessarily the case (true for git-bash, false for cygwin)Unbreathed
U
28

Just use cygpath:

$ cygpath -w "/c/foo/bar"
 -> C:\foo\bar

$ cygpath -u "C:\foo\bar"
 -> /c/foo/bar

You may wonder: "Do I have cygpath installed?" Well,

  1. If you're in git-bash, then yes.
  2. If you're in cygwin or MSYS2, then yes.
  3. If you're in another shell, but you have installed git-bash before, then cygpath can be found at git-bash-install-folder\usr\bin\cygpath.exe.
  4. Else: maybe not, but I'm sure you can find a way to installed it.
Ushas answered 16/9, 2020 at 2:18 Comment(0)
P
9

The "correct" way in MSYS is:

$ MSYS_NO_PATHCONV=1  taskkill /F /T /IM ssh-agent.exe

This avoids having to manually translate slashes. It simply de-activates the path conversion.

Preparation answered 13/11, 2019 at 9:11 Comment(0)
M
4

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

Mori answered 29/7, 2017 at 17:13 Comment(0)
G
4

just FYI - at least for my git version 2.26.2.windows.1 e.g. if I have a path like C:\dev\work_setup\msk, I can go directly to Git Bash and type

cd "C:\dev\work_setup\msk"

this will result in current folder being changed to /c/dev/work_setup/msk - so this type of conversion seems to be done automatically, as long as I put the Windows path inside double quotes. Unfortunately I don't have references to original documentation that would back that up.

Gentlemanfarmer answered 8/1, 2021 at 8:43 Comment(1)
This worked for me whereas "cygpath --unix" did not, it returned the path minus any slashes.Sardonic
S
1

My solution works with a list of folders/files and it's done in 2 steps. Suppose you would like to replace a path from D:\example to /example for a list of file where this Windows path has been repetead.

The first step it changes the backlashes into slashes

grep -lr "D:\\\\example" /parent-folder | xargs -d'\n' sed -i 's+\\+\/+g'

Note that parent-folder could be root (/) or whatever you like and -d'\n' parameter is necessary if you have filenames or folder names with white spaces.

Second step it substitutes the D:/example into /example:

grep -lr "D:/example" /parent-folder | xargs -d'\n' sed -i 's+D:+/example+g'

I wanted to share this solution since it tooks me some time to make this 2 lines but it has been really helpfull job (I'm migrating a Windows App to a Linux Server with tons of Windows paths inside').

Samellasameness answered 19/10, 2020 at 9:13 Comment(0)
B
1

The answer of @hello_earth is misleading, due to Windows path must be double backslashed like:

cd "e:\\dir\\subdir\\path"

otherwise the shell will find escape-sequences.

Benzedrine answered 7/6, 2021 at 19:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.