72

I have a windows batch script that uses Windows Ubuntu Bash. It receives a full Windows path as an argument and then passes that path to a command in Ubuntu Bash.

@echo off
bash -lic 'ffmpeg -i "%1" output.avi'

Here "%1" is the full Windows path, like "C:\some path\file.avi"

The command gives the error:

C:some pathfile.avi: Protocol not found

What can I do to have this Windows path convert to a path like /mnt/c/some\ path/file.avi which the Windows Bash would actually understand?

1
  • 1
    What you need is replacing all occurences of C: with /mnt/c (potentially for other drive letters, too), right? Commented Aug 15, 2016 at 8:28

6 Answers 6

105

Windows Build 17046 [1] contains new wslpath utility that can translate paths from/to WSL/Windows. This was known missing WSL feature. [2]

Example usage:

$ echo $0
/bin/bash

$ which wslpath
/bin/wslpath

$ wslpath -a 'C:\\aaa\\bbb\\ccc\\foo.zip'
/mnt/c/aaa/bbb/ccc/foo.zip

You can call wslpath from Powershell on Windows:

>>> wsl wslpath -a 'C:\\aaa\\bbb\\ccc\\foo.zip'
/mnt/c/aaa/bbb/ccc/foo.zip

wslpath options and parameters:

-a    force result to absolute path format
-u    translate from a Windows path to a WSL path (default)
-w    translate from a WSL path to a Windows path
-m    translate from a WSL path to a Windows path, with ‘/’ instead of ‘\\’

Edit (05/24)

If you need the opposite conversion, i.e. to get a path suitable for WSL in PowerShell, you can use:

$pathInWSL = wsl wslpath -a -u "$(Get-Location)\foo.txt".Replace('\', '\\')
# "$(Get-Location)\foo.txt".Replace('\', '\\') = C:\\bar\\baz\\foo.txt
# $pathInWSL = /mnt/c/bar/baz/foo.txt

wsl cat $pathInWSL
# content of /mnt/c/bar/baz/foo.txt
9
  • 1
    For older Windows, available here: github.com/laurent22/wslpath Commented Aug 16, 2018 at 15:11
  • 3
    posh needs escaping '\', but wsl not. your example $ wslpath -a 'C:\\aaa\\bbb\\ccc\\foo.zip' should be $ wslpath -a 'C:\aaa\bbb\ccc\foo.zip' It works when escaped, but useless escaping is confusing. One could assume it must be escaped. Also, I think description on -m, ... with ‘/’ instead of ‘\\’ should have one ‘\’ (I know it's copy-pasted) If you do wslpath -w /mnt/c/Users, it does not print two ‘\\’
    – papo
    Commented Dec 10, 2018 at 15:00
  • 5
    I believe that wslpath is part of the answer, but I believe that this post does not functionally answer the question — which asks, when a batch file has a Windows-style (C:\foo\bar\blah) name for a data file, how does it run a WSL command on that file? Commented Apr 28, 2019 at 15:22
  • 1
    How to call wslpath with a variable which I can't escape? I have a powershell script with line wsl wslpath -a "$PSScriptRoot" and it returns wslpath: C:Folder1Folder2
    – Zikato
    Commented Feb 11, 2022 at 12:07
  • 2
    How do we make this work from a batch file where the filename is not double-backslashed?
    – Brent K.
    Commented Sep 20, 2022 at 13:19
7

I wrote a bat file to do this. Just place the file wherever you are working or add it to your path (or just put it above your code, which would be easier to work with). Remember to assign "variable" to your file path first (if you are using a separate file, try using parameters).

What the code does:

1) Get the first letter of the path, which is the drive.

2) Remove the first two letters.

3) Change the slashes.

4) This is the tricky part: since Linux is case sensitive, we need to convert uppercase drive letter to lowercase. Do this by matching each (tell me if there is a better way). You can remove unnecessary drive letters too, since you probably have no more than ten drives.

5) Combine everything to give the final string.

The result:

Input:

E:\myfiles\app1\data\file.csv

Output (with the quotation marks):

"/mnt/e/myfiles/app1/data/file.csv"

The code is as follows:

@echo OFF

set "variable=E:\myfiles\app1\data\file.csv"

set "drive=%variable:~0,1%"

set variable=%variable:~2%
set "variable=%variable:\=/%"

if %drive%==A set "drive=a"
if %drive%==B set "drive=b"
if %drive%==C set "drive=c"
if %drive%==D set "drive=d"
if %drive%==E set "drive=e"
if %drive%==F set "drive=f"
if %drive%==G set "drive=g"
if %drive%==H set "drive=h"
if %drive%==I set "drive=i"
if %drive%==J set "drive=j"
if %drive%==K set "drive=k"
if %drive%==L set "drive=l"
if %drive%==M set "drive=m"
if %drive%==N set "drive=n"
if %drive%==O set "drive=o"
if %drive%==P set "drive=p"
if %drive%==Q set "drive=q"
if %drive%==R set "drive=r"
if %drive%==S set "drive=s"
if %drive%==T set "drive=t"
if %drive%==U set "drive=u"
if %drive%==V set "drive=v"
if %drive%==W set "drive=w"
if %drive%==X set "drive=x"
if %drive%==Y set "drive=y"
if %drive%==Z set "drive=z"

set "variable=/mnt/%drive%%variable%"

echo "%variable%"

@echo ON
6
  • What about the reverse, converting a Unix path to a Windows path in a shell script? Commented Mar 30, 2017 at 13:29
  • @JacobTheDev, you would need only slight modifications for that ;)
    – pulsejet
    Commented Mar 30, 2017 at 13:41
  • actually figured it out this morning! gist.github.com/JacobDB/e71e22c3663175b2369211aeb54362fe Commented Mar 31, 2017 at 16:32
  • What is the advantage of your code over wlspath? Why not powershell, but old-school?
    – Timo
    Commented Jan 3, 2021 at 12:07
  • @Timo see the date of the answer :)
    – pulsejet
    Commented Jan 4, 2021 at 10:35
5

Why so complicated?

Change the registry entry

HKEY_CLASSES_ROOT\Applications\bash.exe\shell\open\command

from

C:\Windows\System32\wsl.exe "%1"

to

C:\Windows\System32\wsl.exe `wslpath '%1'`

Use backticks before wslpath and at the end, and use single quotation marks (straight ticks) around %1.

Works for me.

2
  • Really?  This solves the problem in the question, where bash is called from a batch file? (Note that, in the example, bash’s first argument is -lic, so it’s not clear to me how wslpath '%1' is going to work.) And why have you changed from double quotes ("%1") to single quotes ('%1')? Commented Apr 28, 2019 at 15:06
  • Plus one, I like it.
    – Timo
    Commented Jan 3, 2021 at 12:05
3

This simple solution works for files on the C drive:

@echo off
set X=%1
set X=%X:\=/%
set X=%X:C:=/mnt/c%
bash -lic 'ffmpeg -i "%X%" output.avi'
3

this is my cdwin script, change win dir to wsl path

#!/bin/bash
line=$(sed -e 's~\\~/~g' -e "s/\([CD]\):/\L\1/" -e "s/^/\/mnt\//g" <<< "$1")
cd $line

Use:

#:cdwin 'C:\Users\win\Documents'
#:/mnt/c/Users/win/Documents$

0

Use the cygpath tool:

Unix to windows: $ cygpath -w /d/temp D:\temp

Windows to unix: $ cygpath -u 'D:\temp' /d/temp

https://dev.to/taijidude/paths-conversion-in-git-bash-3jeh

1
  • 1
    Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
    – Community Bot
    Commented Feb 5 at 11:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .