Konwertuj ścieżkę Windows dla Windows Ubuntu Bash

32

Mam skrypt wsadowy systemu Windows korzystający z systemu Windows Ubuntu Bash. Otrzymuje pełną ścieżkę systemu Windows jako argument, a następnie przekazuje tę ścieżkę do polecenia w Ubuntu Bash.

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

Oto "%1"pełna ścieżka systemu Windows"C:\some path\file.avi"

Polecenie podaje błąd:

C:some pathfile.avi: Protocol not found

Co mogę zrobić, aby ta ścieżka systemu Windows została przekonwertowana na ścieżkę podobną do tej, /mnt/c/some\ path/file.aviktórą program Windows Bash faktycznie zrozumiałby?

laggingreflex
źródło
Co trzeba jest zastąpienie wszystkich wystąpień C:z /mnt/c(potencjalnie dla innych liter dysków, zbyt), prawda?
kleinfreund

Odpowiedzi:

41

Kompilacja systemu Windows 17046 [1] zawiera nowe wslpathnarzędzie, które może tłumaczyć ścieżki z / na WSL / Windows. To była znana brakująca funkcja WSL. [2]

Przykładowe użycie:

$ echo $0
/bin/bash

$ which wslpath
/bin/wslpath

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

Możesz zadzwonić wslpathz programu Powershell w systemie Windows:

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

wslpath opcje i parametry:

-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 ‘\\’
illagrenan
źródło
1
W przypadku starszych systemów Windows dostępny tutaj: github.com/laurent22/wslpath
Chimpanzee
1
posh potrzebuje znaku ucieczki „\”, ale wsl nie. twoim przykładem $ wslpath -a 'C:\\aaa\\bbb\\ccc\\foo.zip'powinno być $ wslpath -a 'C:\aaa\bbb\ccc\foo.zip'To działa, gdy uciekasz, ale bezużyteczne uciekanie jest mylące. Można przypuszczać, że trzeba uciec. Także myślę, że na opis -m, ... with ‘/’ instead of ‘\\’powinny mieć jeden „\” (wiem, że to kopia wklejony) Jeśli tak wslpath -w /mnt/c/Users, to nie drukuje dwa „\\”
Papo
1
Wierzę, że wslpathjest to część odpowiedzi, ale wierzę, że ten post nie odpowiada funkcjonalnie na pytanie - które pyta, kiedy plik wsadowy ma C:\foo\bar\blahnazwę pliku danych w stylu Windows ( ), w jaki sposób uruchamia polecenie WSL na ten plik?
Scott
@papo Właśnie natknąłem się na problem z ukośnikami usecaped: jest niespójny i zależy od tego, jak jest uruchamiany, po uruchomieniu z PowerShell po prostu pomija ukośniki, podczas uruchamiania z bash traktuje je poprawnie tylko wewnątrz ciągu.
sukhmel
@sukhmel true, w wsl (na którym uruchamia się bash dla systemu Windows), a także w konsoli cmd, albo wstaw ścieżkę do pojedynczych lub podwójnych cudzysłowów, albo ucieknij jako \\ Niepotrzebność ucieczki wewnątrz cudzysłowów oferuje szybki sposób: cat `wslpath 'następnie przeciągnij i upuść plik do konsoli i dokończ linię:'`
papo
5

Aby to zrobić, napisałem plik nietoperza. Po prostu umieść plik gdziekolwiek pracujesz lub dodaj go do swojej ścieżki (lub po prostu umieść go nad kodem, co byłoby łatwiejsze do pracy). Pamiętaj, aby najpierw przypisać „zmienną” do ścieżki pliku (jeśli używasz osobnego pliku, spróbuj użyć parametrów).

Co robi kod:

1) Uzyskaj pierwszą literę ścieżki, którą jest dysk.

2) Usuń pierwsze dwie litery.

3) Zmień ukośniki.

4) Jest to trudna część: ponieważ Linux rozróżnia małe i duże litery, musimy przekonwertować wielką literę dysku na małe litery. Zrób to, dopasowując każdy z nich (powiedz mi, czy jest lepszy sposób). Możesz także usunąć niepotrzebne litery dysków, ponieważ prawdopodobnie nie masz więcej niż dziesięć dysków.

5) Połącz wszystko, aby dać końcowy ciąg.

Wynik:

Wejście:

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

Dane wyjściowe (ze znakami cudzysłowu):

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

Kod jest następujący:

@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
PulseJet
źródło
Co powiesz na odwrócenie, konwertowanie ścieżki uniksowej na ścieżkę systemu Windows w skrypcie powłoki?
JacobTheDev
@JacobTheDev, do tego potrzebne byłyby tylko niewielkie modyfikacje;)
PulseJet
Rozpracowałem to dziś rano! gist.github.com/JacobDB/e71e22c3663175b2369211aeb54362fe
JacobTheDev
0

Dlaczego tak skomplikowane?

Zmień wpis rejestru

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

od

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

do

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

Użyj odwrotnych znaków przed wslpath i na końcu oraz użyj pojedynczych cudzysłowów (prostych tików) wokół% 1.

Pracuje dla mnie.

Stefan Oskamp
źródło
Naprawdę? To rozwiązuje problem w pytaniu, gdzie bashjest wywoływany z pliku wsadowego? (Zauważ, że w tym przykładzie pierwszym argumentem bash jest -lic, więc nie jest dla mnie jasne, jak wslpath '%1'to będzie działać.) Dlaczego zmieniłeś z podwójnych cudzysłowów ( "%1") na pojedyncze cudzysłowy ( '%1')?
Scott