[ACCEPTED]-msys path conversion (or cygpath for msys?)-cygpath
Update (Aug-2016):
This question is no longer relevant, as 28 msys2 now comes with cygpath
in its installation.
...
I'll 27 summarize my research here.
The cygpath equivalent 26 in MSYS is to use this command:
{ cd /c/some/path && pwd -W; } | sed 's|/|\\|g'
The problem 25 with this approach is that it requires existing 24 path, e.g. the c:\some\path
has to be an existing directory; however, real 23 cygpath supports paths that do not exist.
So, if 22 you need to get path to a directory that 21 doesn't exist, then you can fallback to 20 sed conversion of the path:
{ cd 2>/dev/null /c/some/path && pwd -W ||
echo /c/some/path | sed 's|^/\([a-z,A-Z]\)/|\1:/|'; } | sed 's|/|\\|g'
The mouthful 19 of slashes is there to satisfy quoting rules 18 of sed
. So, if c:\some\path
doesn't exist on your PC, it 17 will try to convert forward to back slashes 16 and replace /c/
with c:\
(or any other drive letter). The 15 only drawback for this is that it won't 14 work correctly non-existing paths that contain 13 a mounted component, such as /bin/does-not-exist
or /usr/bin/does-not-exist
.
One more 12 approach is to use cygpath from cygwin in MSYS. It 11 seems that cygwin sets global environment 10 variable CYGPATH, that is, you can use it 9 from regular cmd.exe:
%CYGPATH% -w /c/some/path
C:\some\path
or from MSYS:
$CYGPATH -w /c/some/path
C:\some\path
as long 8 as you set to point /c
to /cygdrive/c
in cygwin.
But 7 this approach will print you /usr
located in 6 cygwin installation, not in MSYS.
In short, I 5 think msys should really include real cygpath 4 in the default set of tools just for some 3 cases that aren't handled automatically 2 by msys command line argument conversion 1 logic
use pwd -W
or download cygpath for msys from here 1 http://mingw.5.n7.nabble.com/enhanced-version-of-cygpath-td28556.html
and use cygpath -wa
Similar to dmitri-rubinstein@ above, I've 2 cleaned up the code a bit and added the 1 reverse conversion as well.
winpath() {
if [ ${#} -eq 0 ]; then
: skip
elif [ -f "$1" ]; then
local dirname=$(dirname "$1")
local basename=$(basename "$1")
echo "$(cd "$dirname" && pwd -W)/$basename" \
| sed \
-e 's|/|\\|g';
elif [ -d "$1" ]; then
echo "$(cd "$1" && pwd -W)" \
| sed \
-e 's|/|\\|g';
else
echo "$1" \
| sed \
-e 's|^/\(.\)/|\1:\\|g' \
-e 's|/|\\|g'
fi
}
unixpath() {
echo "$1" \
| sed -r \
-e 's/\\/\//g' \
-e 's/^([^:]+):/\/\1/'
}
I am using this with msysgit:
winpath() {
if [ -z "$1" ]; then
echo "$@"
else
if [ -f "$1" ]; then
local dir=$(dirname "$1")
local fn=$(basename "$1")
echo "$(cd "$dir"; echo "$(pwd -W)/$fn")" | sed 's|/|\\|g';
else
if [ -d "$1" ]; then
echo "$(cd "$1"; pwd -W)" | sed 's|/|\\|g';
else
echo "$1" | sed 's|^/\(.\)/|\1:\\|g; s|/|\\|g';
fi
fi
fi
}
0
My bash foo is weak and I couldn't get regexes 2 working in bash 3.1 so I hacked out a perl 1 script for it:
#!/bin/env perl
use strict;
my @r;
foreach my $e (@ARGV) {
$e=~s/\//\\/g;
$e=~s/^\\([A-Za-z])\\/\1:\\/;
push @r, $e;
}
print join(" ", @r);
MSYS cygpath
Program
This program convert a DOS path to a UNIX 6 path and vice versa
#!/bin/env perl
# DOS to UNIX path conversion
# © John S. Peterson. License GNU GPL 3.
use strict;
use Getopt::Std;
# usage
if ($#ARGV == -1) {
print 'Usage: cygpath (-w) NAME...
Convert Unix and Windows format paths
Output type options:
-w, --windows print Windows form of NAMEs (C:\WINNT)
';
exit 0;
}
# option
my %opt;
getopts('w', \%opt);
# convert path
my @r;
foreach my $e (@ARGV) {
if ($opt{w}) {
# add drive letter suffix
$e =~ s,^\/([A-Za-z])\/,\1:\/,;
$e =~ s,\/,\\,g;
} else {
$e =~ s,\\,\/,g;
# add leading slash
$e = "/$e";
# remove drive letter suffix
$e =~ s,:,,;
}
push @r, $e;
}
print join("\n", @r);
Compared to Cygwin cygpath
The output from this 5 program is better than the output from Cygwin 4 cygpath
in MSYS because
- Cygwin
cygpath
remove the Cygwin home from a converted path, f.e.
cygpath "$CYGWIN/usr/local/bin"
/usr/local/bin
which is a problem because
- it's sometimes useful to convert a DOS Cygwin path to a UNIX path for the purpose of copying files from Cygwin to MSYS
This 3 program doesn't remove the Cygwin home
cygpath "$CYGWIN/usr/local/bin"
/c/file/program/cygwin/usr/local/bin
Compared to automatic MSYS path conversion
Manual 2 path conversion has a use in MSYS because
- the automatic path conversion is inadequate
for 1 f.e.
How about this one ?
cmd //c echo <your path>
It may not work always 1 but it is the shortest I found
nearly pure GNU bash solution (which is what you 10 commonly run in MSYS) (interestingly not 9 working with MSYS2, leave a comment if you 8 know why):
#!/bin/bash
# check if we have cygpath (cygwin, newer MSYS2), then just use that
which cygpath 1>/dev/null 2>&1
[[ $? = 0 ]] && (cygpath -wa "$1"; exit $?)
# check if it looks like a Windows path, in which case we directly convert and exit
[[ ${1} =~ ^[a-zA-Z]: ]] && \
echo "${1}" | sed -e 's|/|\\|g' -e 's/\(.\)/\u\1/' && exit 0
# split first path entry (if any) with trailing slash and filename
[[ ${1} =~ ^\([/a-zA-Z0-9_.-]\\w*/\)?\(.*\)$ ]]
chk_root="${BASH_REMATCH[1]}"
chk_rest="${BASH_REMATCH[2]}"
# check if the root path exists and more important: let pwd binary resolve the translation according to the mount
chk_winroot="$(cd "${chk_root}." 2>/dev/null && pwd -W)"
[[ "${chk_winroot}" == "" ]] && echo "${chk_root}: No such file or directory" && exit 1
# using substition to replace all / by \ and uppercasing the first character
# pure bash solution; sadly: the first part needs a newer bash than old MSYS have ...
# chk_drv="${chk_winroot:0:1}"
# chk_all="${chk_winroot:1}/${chk_rest}"
# echo "${chk_drv^^}${chk_all//\//\\}"
# ... so fallback to GNU sed
echo "${chk_winroot}/${chk_rest}" | sed -e 's|/|\\|g' -e 's/\(.\)/\u\1/'
There's still an issue with it: if 7 MinGW's fstab contains an entry like /mnt/c
the 6 pwd -W
of /mnt/.
done in this script won't work.
To 5 fix it: replace pwd -W
by inspecting $ cat /etc/fstab | cut -d'#' -f1 | grep -v "^\s*$"
entries 4 manually and replace the first match - while 3 this will never work for cygwin or msys2 2 which use a different format this is covered 1 by using cygpath there.
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.