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?
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.
$PATH
is the standard envvar. –
Occlusive $PATH
to be a user-defined variable; I'll edit. –
Boozy sed
, just pass multiple -e command
arguments to single instance (like sed -e one -e two
). –
Orgulous echo "$pth" | sed -e 's#\\#/#g' -e 's#\$#/\\$#g' -e 's#^\([a-zA-Z]\):#/\L\1#
–
Tiltyard echo "$pth" | sed -e 's/\\/\//g' -e 's/\([a-zA-Z]\):/\/\1/g'
–
Retiarius 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 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 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'
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 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 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-bash –
Ushas 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.
$PATH
is the standard envvar. –
Occlusive $PATH
to be a user-defined variable; I'll edit. –
Boozy sed
, just pass multiple -e command
arguments to single instance (like sed -e one -e two
). –
Orgulous echo "$pth" | sed -e 's#\\#/#g' -e 's#\$#/\\$#g' -e 's#^\([a-zA-Z]\):#/\L\1#
–
Tiltyard echo "$pth" | sed -e 's/\\/\//g' -e 's/\([a-zA-Z]\):/\/\1/g'
–
Retiarius 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 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 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,
- If you're in git-bash, then yes.
- If you're in cygwin or MSYS2, then yes.
- If you're in another shell, but you have installed git-bash before, then
cygpath
can be found atgit-bash-install-folder\usr\bin\cygpath.exe
. - Else: maybe not, but I'm sure you can find a way to installed it.
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.
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 2
nd /
. I use ,
for delim instead of /
for readability. If starting with /
(\,^/,
), then replace /
with :/
for the 2
nd 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
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.
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').
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.
© 2022 - 2024 — McMap. All rights reserved.