Converter caminho do Windows para Windows Ubuntu Bash

31

Eu tenho um script em lote do Windows que usa o Windows Ubuntu Bash. Ele recebe um caminho completo do Windows como argumento e passa esse caminho para um comando no Ubuntu Bash.

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

Aqui "%1"está o caminho completo do Windows, como"C:\some path\file.avi"

O comando fornece o erro:

C:some pathfile.avi: Protocol not found

O que posso fazer para que esse caminho do Windows seja convertido em um caminho /mnt/c/some\ path/file.avique o Windows Bash realmente entenderia?

atraso
fonte
O que você precisa é substituir todas as ocorrências de C:por /mnt/c(potencialmente para outras letras de unidade também), certo?
precisa saber é o seguinte

Respostas:

41

O Windows Build 17046 [1] contém um novo wslpathutilitário que pode converter caminhos de / para WSL / Windows. Isso era conhecido como falta do recurso WSL. [2]

Exemplo de uso:

$ echo $0
/bin/bash

$ which wslpath
/bin/wslpath

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

Você pode ligar wslpathdo Powershell no Windows:

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

wslpath opções e parâmetros:

-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
fonte
1
Para mais antigo do Windows, disponível aqui: github.com/laurent22/wslpath
Warlike Chimpanzé
1
elegante precisa escapar de '\', mas não. seu exemplo $ wslpath -a 'C:\\aaa\\bbb\\ccc\\foo.zip'deve ser $ wslpath -a 'C:\aaa\bbb\ccc\foo.zip'. Funciona quando escapado, mas escapar inútil é confuso. Pode-se supor que deve ser escapado. Além disso, acho descrição sobre -m, ... with ‘/’ instead of ‘\\’deve ter um '\' (eu sei que é cópia colado) Se você fizer isso wslpath -w /mnt/c/Users, ele não imprimir dois '\\'
papo
1
Acredito que wslpathseja parte da resposta, mas acredito que esta postagem não responde funcionalmente à pergunta - que pergunta, quando um arquivo em lotes tem um C:\foo\bar\blahnome no estilo Windows ( ) para um arquivo de dados, como ele executa um comando WSL em esse arquivo?
Scott
@papo Acabei de me deparar com um problema com barras inutilizadas: é inconsistente e depende de como é executado, quando executado a partir do PowerShell apenas omite barras inutilizadas, quando executado a partir do bash as trata corretamente apenas dentro de uma string.
sukhmel
@sukhmel true, no wsl (no qual o bash para Windows é executado) e também no console do cmd, coloque o caminho entre aspas simples ou duplas ou escape como \\ A falta de precisão de escapar entre aspas oferece uma maneira rápida de fazer: cat `wslpath 'arraste e solte um arquivo no console e termine a linha:'`
papo
5

Eu escrevi um arquivo bat para fazer isso. Coloque o arquivo onde quer que esteja trabalhando ou adicione-o ao seu caminho (ou apenas coloque-o acima do seu código, o que seria mais fácil de trabalhar). Lembre-se de atribuir "variável" ao caminho do arquivo primeiro (se você estiver usando um arquivo separado, tente usar parâmetros).

O que o código faz:

1) Obtenha a primeira letra do caminho, que é a unidade.

2) Remova as duas primeiras letras.

3) Mude as barras.

4) Esta é a parte complicada: como o Linux faz distinção entre maiúsculas e minúsculas, precisamos converter a letra da unidade maiúscula em minúscula. Faça isso combinando cada um (diga-me se existe uma maneira melhor). Você também pode remover letras de unidade desnecessárias, pois provavelmente não possui mais que dez unidades.

5) Combine tudo para dar a sequência final.

O resultado:

Entrada:

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

Saída (com aspas):

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

O código é o seguinte:

@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
fonte
E o contrário, convertendo um caminho Unix para um caminho do Windows em um script de shell?
JacobTheDev
@JacobTheDev, você só precisa de pequenas modificações para que;)
pulsejet
realmente descobri esta manhã! gist.github.com/JacobDB/e71e22c3663175b2369211aeb54362fe
JacobTheDev
0

Por que tão complicado?

Alterar a entrada do registro

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

a partir de

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

para

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

Use backticks antes de wslpath e no final e use aspas simples (marcações retas) em torno de% 1.

Funciona para mim.

Stefan Oskamp
fonte
Verdade? Isso resolve o problema na pergunta, onde bashé chamado de um arquivo em lotes? (Observe que, no exemplo, o primeiro argumento do bash é -lic, então não está claro para mim como wslpath '%1'vai funcionar.) E por que você mudou de aspas duplas ( "%1") para aspas simples ( '%1')?
Scott