Ścieżka plików systemu Windows przekonwertowana na ścieżkę plików systemu Linux


13

Mam ścieżkę systemu Windows w zmiennej bash jako ciąg:

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

Próbuję przekonwertować tę ścieżkę na ścieżkę Linuksa zaczynając od /c/Users....

Moja próba

Następujące prace:

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

Problem

Tutaj zrobiłem to dla ciągu zawierającego ścieżkę do pliku. Powodem, dla którego zadaję to pytanie, jest to, że muszę przekonwertować 20 takich ciągów w skrypcie bash w Ubuntu 16.04 i za każdym razem, gdy to robię, muszę napisać 2 wiersze na konwersję - zajmuje to dużo miejsca!

Pytanie

Czy istnieje sposób na połączenie 2 poleceń

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

w jednym poleceniu?


1
Użyj pętli for (a może tablicy). Podaj także swoje zmienne.
wjandrea,

Dzięki. Czy możesz pokazać przykład, jak to zrobić w pętli lub tablicy?
edesz

Odpowiedzi:


17

Byłby sposób na wykonanie obu wymian jednocześnie sed, ale nie jest to konieczne.

Oto jak rozwiązałbym ten problem:

  1. Umieść nazwy plików w tablicy
  2. Iteruj po tablicy

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

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

Jeśli chcesz umieścić dane wyjściowe w tablicy zamiast drukowania, zamień echowiersz na przypisanie:

  filenames_out+=( "$f" )

Ok, ale gdybym miał 2 pliki f1i f2jak by to działało? To znaczy, jak mam przypisać nowe nazwy plików do tablicy, zastępując stare?
edesz

@WR umieść je w nowej tablicy i użyj tego.
muru

@WR Dodał to do odpowiedzi
wjandrea,

1
Dla jasności poleciłbym stworzyć nową tablicę.
wjandrea,

9

Jeśli chcesz to zrobić wiele razy, to dlaczego nie stworzyć małej funkcji powłoki?

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

To nie jest zły pomysł. Jednak wydaje się, że nie daje /c/Users...- zamiast tego daje C:\Users\....
edesz,

@WR przeprosiny - błąd kopiuj-wklej. Spróbuj teraz.
steeldriver

1
Dzięki, używam cdw () { f="${1/D://d}"; cd "/mnt${f//\\//}"; }w podsystemie Windows dla Linuksa, działa jak urok!
Weekend

2

Byłbyś w stanie to osiągnąć w jednej linii za pomocą sed

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

Zauważ, że oba wzorce muszą pozostać oddzielne, ponieważ dopasowania są zastępowane przez różne podstawienia.


1
Synonim:file="$(sed 's|^C:|/c|; s|\\|/|g' <<< "$file")"
wjandrea,

1

Czy to pytanie jest nadal otwarte na nowe sugestie? Jeśli tak, czy to by ci pomogło?

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

Aha, a jeśli C musi być rzucone na małe litery:

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

Jako przegląd:

$ 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

Jaki jest powód korzystania '^C'?
edesz

1
^ oznacza początek wiersza, w przeciwnym razie wszystkie wystąpienia litery C będą

Muszę dodać, że inne sugestie również działają. Wiele poleceń Uniksa może wykonywać tę samą pracę, więc od Ciebie zależy, jaki styl rozwiązania preferujesz.

Nie pytałem wcześniej o ^to, co zostało wykorzystane w innych odpowiedziach tutaj. Dziękuję za odpowiedź i wyjaśnienie.
edesz
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.