Convertir le chemin Windows pour Windows Ubuntu Bash

30

J'ai un script batch Windows qui utilise Windows Ubuntu Bash. Il reçoit un chemin d'accès Windows complet en tant qu'argument, puis le transmet à une commande dans Ubuntu Bash.

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

Voici "%1"le chemin complet de Windows, comme"C:\some path\file.avi"

La commande donne l'erreur:

C:some pathfile.avi: Protocol not found

Que puis-je faire pour convertir ce chemin Windows en un chemin comme celui /mnt/c/some\ path/file.avique Windows Bash comprendrait réellement?

réflexe de retard
la source
Ce dont vous avez besoin, c'est de remplacer toutes les occurrences de C:par /mnt/c(éventuellement pour d'autres lettres de lecteur), n'est-ce pas?
kleinfreund

Réponses:

40

Windows Build 17046 [1] contient un nouvel wslpathutilitaire capable de convertir les chemins de / vers WSL / Windows. Cette fonctionnalité manquait dans WSL. [2]

Exemple d'utilisation:

$ echo $0
/bin/bash

$ which wslpath
/bin/wslpath

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

Vous pouvez appeler wslpathdepuis Powershell sous Windows:

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

wslpath options et paramètres:

-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
la source
1
Pour les anciennes versions de Windows, disponible ici: github.com/laurent22/wslpath
Chimpanzé guerrier
1
posh a besoin de s'échapper '\', mais wsl pas. Votre exemple $ wslpath -a 'C:\\aaa\\bbb\\ccc\\foo.zip'devrait être: $ wslpath -a 'C:\aaa\bbb\ccc\foo.zip'ça marche quand on s’évade, mais s’évader inutilement est déroutant. On pourrait supposer qu'il faut s'échapper. En outre, je pense que la description -m, ... with ‘/’ instead of ‘\\’devrait avoir un '\' (je sais que c'est un copier-coller) Si vous le faites wslpath -w /mnt/c/Users, il n'imprime pas deux '\\'
papo
1
Je pense que cela wslpathfait partie de la réponse, mais je pense que cet article ne répond pas de manière fonctionnelle à la question - qui demande, lorsqu'un fichier de commandes a un C:\foo\bar\blahnom de style Windows ( ) pour un fichier de données, comment exécute-t-il une commande WSL sur ce fichier?
Scott
@papo Je viens de trébucher sur un problème avec les barres obliques: celles-ci sont incohérentes et dépendent de la façon dont elles sont exécutées. Lorsqu'elles sont exécutées à partir de powershell, elles omettent simplement les barres obliques non échappées.
Sukhmel le
@sukhmel vrai, dans WSL (sur lequel bash pour Windows fonctionne) et aussi dans la console cmd, soit chemin mis entre guillemets simples ou doubles, ou échapper comme \\ Le unneccesity d'échapper à l' intérieur de citations offre un moyen rapide de faire: cat `wslpath 'puis glisser-déposer une déposer dans la console et terminer la ligne:'`
papo
5

J'ai écrit un fichier chauve-souris pour le faire. Il suffit de placer le fichier où que vous soyez ou de l'ajouter à votre chemin (ou simplement de le placer au-dessus de votre code, ce qui serait plus facile). N'oubliez pas d'affecter d'abord «variable» à votre chemin de fichier (si vous utilisez un fichier séparé, essayez d'utiliser des paramètres).

Que fait le code:

1) Obtenez la première lettre du chemin, qui est le lecteur.

2) Enlevez les deux premières lettres.

3) Changer les barres obliques.

4) C’est la partie la plus délicate: comme Linux est sensible à la casse, nous devons convertir la lettre du lecteur en majuscule en minuscule. Faites-le en faisant correspondre chaque (dites-moi s'il y a un meilleur moyen). Vous pouvez également supprimer les lettres de lecteur inutiles, car vous n’avez probablement pas plus de dix lecteurs.

5) Tout combiner pour donner la dernière chaîne.

Le résultat:

Contribution:

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

Sortie (avec les guillemets):

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

Le code est comme suit:

@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
la source
Et inversement, convertir un chemin Unix en chemin Windows dans un script shell?
JacobTheDev
@JacobTheDev, vous n'aurez besoin que de légères modifications pour cela;)
PulseJet
effectivement compris ce matin! gist.github.com/JacobDB/e71e22c3663175b2369211aeb54362fe
JacobTheDev
0

Pourquoi si compliqué?

Changer l'entrée du registre

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

de

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

à

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

Utilisez des guillemets avant wslpath et à la fin, et utilisez des guillemets simples (ticks droits) autour de% 1.

Travaille pour moi.

Stefan Oskamp
la source
Vraiment? Cela résout le problème dans la question, où bashest appelé à partir d'un fichier de commandes? (Notez que, dans l'exemple, le premier argument de bash est -lic, il n'est donc pas clair pour moi comment ça wslpath '%1'va fonctionner.) Et pourquoi avez-vous changé de guillemets doubles ( "%1") à guillemets simples ( '%1')?
Scott