Convertir la ruta de Windows para Windows Ubuntu Bash

31

Tengo un script por lotes de Windows que usa Windows Ubuntu Bash. Recibe una ruta completa de Windows como argumento y luego pasa esa ruta a un comando en Ubuntu Bash.

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

Aquí "%1"está la ruta completa de Windows, como"C:\some path\file.avi"

El comando da el error:

C:some pathfile.avi: Protocol not found

¿Qué puedo hacer para que esta ruta de Windows se convierta en una ruta como la /mnt/c/some\ path/file.avique Windows Bash realmente entendería?

laggingreflex
fuente
Lo que necesita es reemplazar todas las ocurrencias de C:con /mnt/c(posiblemente también para otras letras de unidad), ¿verdad?
kleinfreund

Respuestas:

41

Windows Build 17046 [1] contiene una nueva wslpathutilidad que puede traducir rutas de / a WSL / Windows. Esto se sabía que faltaba la función WSL. [2]

Ejemplo 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

Puede llamar wslpathdesde Powershell en Windows:

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

wslpath opciones y 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
fuente
1
Para Windows más antiguos, disponibles aquí: github.com/laurent22/wslpath
Chimpanzee
1
posh necesita escapar de '\', pero wsl no. su ejemplo $ wslpath -a 'C:\\aaa\\bbb\\ccc\\foo.zip'debería ser $ wslpath -a 'C:\aaa\bbb\ccc\foo.zip'Funciona cuando se escapa, pero el escape inútil es confuso. Se podría suponer que se debe escapar. Además, creo que en la descripción -m, ... with ‘/’ instead of ‘\\’debe tener una '\' (Sé que es copia-pegar) Si lo hace wslpath -w /mnt/c/Users, no se imprime dos '\\'
papo
1
Creo que wslpathes parte de la respuesta, pero creo que esta publicación no responde funcionalmente a la pregunta, que pregunta, cuando un archivo por lotes tiene un C:\foo\bar\blahnombre de estilo Windows ( ) para un archivo de datos, ¿cómo ejecuta un comando WSL en ese archivo?
Scott
@papo Acabo de encontrar un problema con las barras inclinadas de uso: es inconsistente y depende de cómo se ejecute, cuando se ejecuta desde PowerShell, simplemente omite barras sin escape, cuando se ejecuta desde bash las trata correctamente solo dentro de una cadena.
sukhmel
@sukhmel true, en wsl (en el que se ejecuta bash para Windows) y también en la consola cmd, ya sea poner ruta en comillas simples o dobles, o escapar como \\ La innecesaria necesidad de escapar entre comillas ofrece una forma rápida de hacerlo: cat `wslpath 'luego arrastre y suelte un presentar en la consola y terminar la línea:'`
papo
5

Escribí un archivo bat para hacer esto. Simplemente coloque el archivo donde sea que esté trabajando o agréguelo a su ruta (o simplemente colóquelo sobre su código, lo que sería más fácil de trabajar). Recuerde asignar primero "variable" a su ruta de archivo (si está usando un archivo separado, intente usar parámetros).

Lo que hace el código:

1) Obtenga la primera letra de la ruta, que es la unidad.

2) Eliminar las dos primeras letras.

3) Cambiar las barras inclinadas.

4) Esta es la parte difícil: dado que Linux distingue entre mayúsculas y minúsculas, necesitamos convertir la letra de la unidad en mayúscula a minúscula. Haga esto haciendo coincidir cada uno (dígame si hay una mejor manera). También puede eliminar letras de unidad innecesarias, ya que probablemente no tenga más de diez unidades.

5) Combina todo para dar la cuerda final.

El resultado:

Entrada:

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

Salida (con las comillas):

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

El código es el siguiente:

@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
fuente
¿Qué pasa con el reverso, convirtiendo una ruta de Unix en una ruta de Windows en un script de shell?
JacobTheDev
@JacobTheDev, solo necesitaría ligeras modificaciones para eso;)
PulseJet
en realidad lo descubrí esta mañana! gist.github.com/JacobDB/e71e22c3663175b2369211aeb54362fe
JacobTheDev
0

¿Por qué tan complicado?

Cambiar la entrada del registro

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

desde

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

a

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

Use las marcas de retroceso antes de wslpath y al final, y use comillas simples (marcas rectas) alrededor de% 1.

Funciona para mi.

Stefan Oskamp
fuente
De Verdad? Esto resuelve el problema en la pregunta, ¿dónde bashse llama desde un archivo por lotes? (Tenga en cuenta que, en el ejemplo, el primer argumento de bash es -lic, así que no me wslpath '%1'queda claro cómo va a funcionar). ¿Y por qué ha cambiado de comillas dobles ( "%1") a comillas simples ( '%1')?
Scott