Конвертировать путь Windows для Windows Ubuntu Bash

32

У меня есть пакетный скрипт Windows, который использует Windows Ubuntu Bash. Он получает полный путь Windows в качестве аргумента, а затем передает этот путь команде в Ubuntu Bash.

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

Вот "%1"полный путь Windows, как"C:\some path\file.avi"

Команда выдает ошибку:

C:some pathfile.avi: Protocol not found

Что я могу сделать, чтобы преобразовать этот путь Windows в путь, подобный тому, /mnt/c/some\ path/file.aviкоторый на самом деле понимает Windows Bash?

laggingreflex
источник
Что вам нужно , это замена всех вхождений C:с /mnt/c(потенциально для других букв, тоже), не так ли?
kleinfreund

Ответы:

41

Windows Build 17046 [1] содержит новую wslpathутилиту, которая может переводить пути из / в WSL / Windows. Это было известно отсутствующей функцией WSL. [2]

Пример использования:

$ echo $0
/bin/bash

$ which wslpath
/bin/wslpath

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

Вы можете позвонить wslpathиз Powershell в Windows:

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

wslpath варианты и параметры:

-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
источник
1
Для более старых версий Windows доступно здесь: github.com/laurent22/wslpath
Воинственный шимпанзе
1
Шикарная требует экранирования '\', но нет. Ваш пример $ wslpath -a 'C:\\aaa\\bbb\\ccc\\foo.zip'должен быть: $ wslpath -a 'C:\aaa\bbb\ccc\foo.zip'Он работает, когда сбежал, но бесполезный выход сбивает с толку. Можно предположить, что это нужно избежать. Кроме того , я думаю , что описание на -m, ... with ‘/’ instead of ‘\\’должны иметь один «\» (я знаю , что это копия-вставили) Если вы делаете wslpath -w /mnt/c/Users, это не печатает два «\\»
Папо
1
Я считаю, что wslpathэто часть ответа, но я считаю, что этот пост не дает функционального ответа на вопрос - который спрашивает, когда пакетный файл имеет имя в стиле Windows ( C:\foo\bar\blah) для файла данных, как он запускает команду WSL на этот файл?
Скотт
@papo Я только что наткнулся на проблему с используемыми слешами: он несовместим и зависит от того, как он работает, при запуске из powershell он просто пропускает неэкранированные слэши, а при запуске из bash он корректно обрабатывает их только внутри строки.
Сухмел
@sukhmel true, в wsl (на котором запускается bash для windows), а также в консоли cmd, либо указывайте путь в одинарных или двойных кавычках, либо экранируйте как \\. Излишняя экранирование внутри кавычек предлагает быстрый способ сделать это: cat `wslpath 'затем перетащите и отпустите '`
введите
5

Я написал файл летучей мыши, чтобы сделать это. Просто поместите файл, где бы вы ни работали, или добавьте его к своему пути (или просто поместите его над вашим кодом, с которым было бы легче работать). Не забудьте сначала назначить «переменную» для вашего пути к файлу (если вы используете отдельный файл, попробуйте использовать параметры).

Что делает код:

1) Получить первую букву пути, который является диск.

2) Удалите первые две буквы.

3) Поменяйте косую черту.

4) Это сложная часть: поскольку Linux чувствителен к регистру, нам нужно преобразовать букву диска в верхний регистр в строчный. Сделайте это путем сопоставления каждого (скажите, есть ли лучший способ). Вы также можете удалить ненужные буквы дисков, так как у вас, вероятно, не более десяти дисков.

5) Объедините все, чтобы получить финальную строку.

Результат:

Входные данные:

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

Вывод (с кавычками):

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

Код выглядит следующим образом:

@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
пульсирующий воздушно-реактивный двигатель
источник
А как же обратное преобразование пути Unix в путь Windows в сценарии оболочки?
JacobTheDev
@JacobTheDev, для этого вам понадобятся лишь небольшие модификации;)
PulseJet
на самом деле понял это сегодня утром! gist.github.com/JacobDB/e71e22c3663175b2369211aeb54362fe
JacobTheDev
0

Почему так сложно?

Изменить запись реестра

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

из

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

в

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

Используйте обратные пометки перед wslpath и в конце и используйте одинарные кавычки (прямые тики) около% 1.

Работает для меня.

Стефан Оскамп
источник
В самом деле? Это решает проблему в вопросе, где bashвызывается из командного файла? (Обратите внимание, что в данном примере первый аргумент bash таков -lic, что мне непонятно, как wslpath '%1'это будет работать.) И почему вы перешли с двойных кавычек ( "%1") на одинарные кавычки ( '%1')?
Скотт