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//\\//}

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

edesz
источник
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" )
wjandrea
источник
Хорошо. Но если бы у меня было 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
steeldriver
источник
Это неплохая идея. Тем не менее, это, кажется, не дает /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')"

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

taifwa
источник
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