Windows filepath преобразуется в Linux filepath


13

У меня есть путь Windows в переменной Bash в виде строки:

file='C:\Users\abcd\Downloads\testingFile.log'

Я пытаюсь преобразовать этот путь в путь Linux, начиная с /c/Users....

Моя попытка

Следующие работы:

file=${file/C://c}
file=${file//\\//}
echo $file
> /c/Users/abcd/Downloads/testingFile.log

проблема

Здесь я сделал это для строки, содержащей путь к файлу. Причина, по которой я задаю этот вопрос, заключается в том, что мне нужно конвертировать 20 таких строк в скрипте bash в Ubuntu 16.04, и каждый раз, когда я делаю это, мне приходится писать по 2 строки на конвертацию - это занимает много места!

Вопрос

Есть ли способ объединить 2 команды

file=${file/C://c}
file=${file//\\//}

в одну команду?


1
Используйте цикл for (и, возможно, массив). Также процитируйте свои переменные.
wjandrea

Благодарю. Не могли бы вы показать пример того, как сделать это в цикле или массиве?
edesz

Ответы:


17

Был бы способ сделать обе замены одновременно sed, но это не обязательно.

Вот как бы я решил эту проблему:

  1. Поместите имена файлов в массив
  2. Итерировать по массиву

filenames=(
  'C:\Users\abcd\Downloads\testingFile.log'
  # ... add more here ...
)

for f in "${filenames[@]}"; do
  f="${f/C://c}"
  f="${f//\\//}"
  echo "$f"
done

Если вы хотите поместить вывод в массив вместо печати, замените echoстроку присваиванием:

  filenames_out+=( "$f" )

Хорошо. Но если бы у меня было 2 файла, f1и f2как бы это работало? Я имею в виду, как мне переназначить новые имена файлов в массиве, заменив старые?
edesz

@WR поместите их в новый массив и используйте его.
Муру

@WR добавил , что в ответ
wjandrea

1
Я бы порекомендовал сделать новый массив для ясности.
wjandrea

9

Если это то, что вы хотите сделать много раз, то почему бы не создать небольшую функцию оболочки?

win2lin () { f="${1/C://c}"; printf '%s\n' "${f//\\//}"; }

$ file='C:\Users\abcd\Downloads\testingFile.log'
$ win2lin "$file"
/c/Users/abcd/Downloads/testingFile.log
$ 
$ file='C:\Users\pqrs\Documents\foobar'
$ win2lin "$file"
/c/Users/pqrs/Documents/foobar

Это неплохая идея. Тем не менее, это, кажется, не дает /c/Users...- вместо этого это дает C:\Users\....
edesz

@WR извинения - ошибка копирования-вставки. Пожалуйста, попробуйте это сейчас.
SteelDriver

1
Спасибо, я использую cdw () { f="${1/D://d}"; cd "/mnt${f//\\//}"; }в Windows подсистему для Linux, работает как шарм!
Выходные

2

Вы сможете достичь этого в одну строку, используя sed

file="$(echo "$file" | sed -r -e 's|^C:|/c|' -e 's|\\|/|g')"

Обратите внимание, что эти два шаблона должны оставаться отдельными, однако совпадения заменяются различными заменами.


1
Синоним:file="$(sed 's|^C:|/c|; s|\\|/|g' <<< "$file")"
wjandrea

1

Этот вопрос все еще открыт для новых предложений? Если это так, поможет ли это вам?

$ file="/$(echo 'C:\Users\abcd\Downloads\testingFile.log'|tr '\\' '/')"
$ echo $file
/C:/Users/abcd/Downloads/testingFile.log

О, и в случае, если C должен быть приведен к нижнему регистру:

file="/$(echo 'C:\Users\abcd\Downloads\testingFile.log'|tr '^C' 'c'|tr '\\' '/')"

В качестве обзора:

$ file='C:\Users\abcd\Downloads\testingFile.log'
$ echo $file
C:\Users\abcd\Downloads\testingFile.log
$ file="/$(echo $file|tr '^C' 'c'|tr '\\' '/')"
$ echo $file
/c:/Users/abcd/Downloads/testingFile.log

Какова причина использования '^C'?
edesz

1
^ означает начало строки, иначе все вхождения C станут строчными ... если таковые будут

Я должен добавить, что другие предложения также работают. Многие команды Unix могут выполнять одну и ту же работу, поэтому вам решать, какой стиль решения вы предпочитаете использовать.

Я не спрашивал ранее о ^том, что здесь использовалось и в некоторых других ответах. Спасибо за ответ и объяснение.
edesz
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.