Windows PATH to posix path conversion in bash

前端 未结 6 1537
北荒
北荒 2020-12-04 16:35

How can I convert a Windows dir path (say c:/libs/Qt-static) to the correct POSIX dir path (/c/libs/Qt-static) by

相关标签:
6条回答
  • 2020-12-04 17:02

    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.

    0 讨论(0)
  • 2020-12-04 17:04

    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.

    0 讨论(0)
  • 2020-12-04 17:12

    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'
    
    0 讨论(0)
  • 2020-12-04 17:12

    If you have ever installed git-bash, then just use cygpath, which comes included with git-bash:

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

    When you're in git-bash, cygpath is in PATH. If you're in cmd or powershell, cygpath is at git-bash-install-folder\usr\bin\cygpath.exe

    cygpath is a util of cygwin, but you don't need to know what cygwin is. The vice versa is also true: if you already have cygwin, then you don't need to know what git-bash is.

    0 讨论(0)
  • 2020-12-04 17:15

    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').

    0 讨论(0)
  • 2020-12-04 17:27

    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

    0 讨论(0)
提交回复
热议问题