Windows-Dateipfad in Linux-Dateipfad konvertiert


13

Ich habe einen Windows-Pfad in einer Bash-Variablen als Zeichenfolge:

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

Ich versuche, diesen Pfad in einen Linux-Pfad umzuwandeln, der mit beginnt /c/Users....

Mein Versuch

Die folgenden Arbeiten:

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

Problem

Hier habe ich das für einen String gemacht, der den Dateipfad enthält. Der Grund, warum ich diese Frage stelle, ist, dass ich 20 solcher Zeichenfolgen in einem Bash-Skript in Ubuntu 16.04 konvertieren muss und jedes Mal, wenn ich dies tue, 2 Zeilen pro Konvertierung schreiben muss - das nimmt viel Platz in Anspruch!

Frage

Gibt es eine Möglichkeit, die 2 Befehle zu kombinieren

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

in einen Befehl?


1
Verwenden Sie eine for-Schleife (und möglicherweise ein Array). Zitieren Sie auch Ihre Variablen.
— wjandrea

Vielen Dank. Können Sie ein Beispiel dafür zeigen, wie dies in einer Schleife oder einem Array durchgeführt wird?
— Edesz

Antworten:


17

Es gibt eine Möglichkeit, beide Ersetzungen gleichzeitig durchzuführen sed, dies ist jedoch nicht erforderlich.

So würde ich dieses Problem lösen:

  1. Fügen Sie die Dateinamen in das Array ein
  2. Über Array iterieren

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

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

Wenn Sie die Ausgabe in ein Array einfügen möchten, anstatt sie zu drucken, ersetzen Sie die echoZeile durch eine Zuweisung:

  filenames_out+=( "$f" )

Ok. Aber wenn ich 2 Dateien hätte f1und f2wie würde das funktionieren? Ich meine, wie kann ich dem Array die neuen Dateinamen zuweisen, indem ich die alten ersetze?
— Edesz

@WR setze sie in ein neues Array und benutze das.
— muru

@WR Fügte das zur Antwort hinzu
— wjandrea

1
Ich würde empfehlen, aus Gründen der Übersichtlichkeit ein neues Array zu erstellen.
— wjandrea

9

Wenn es etwas ist, das Sie oft tun möchten, warum dann nicht eine kleine Shell-Funktion erstellen?

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

Das ist keine schlechte Idee. Es scheint jedoch nicht zu geben /c/Users...- stattdessen gibt es C:\Users\....
— Edesz

@ WR Entschuldigung - Copy-Paste-Fehler. Bitte versuchen Sie es jetzt.
— Steeldriver

1
Danke, ich benutze cdw () { f="${1/D://d}"; cd "/mnt${f//\\//}"; }im Windows-Subsystem für Linux, funktioniert wie ein Zauber!
— Wochenende

2

Mit sed können Sie dies in einer Zeile erreichen

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

Beachten Sie, dass die beiden Muster dennoch getrennt bleiben müssen, da die Übereinstimmungen durch unterschiedliche Substitutionen ersetzt werden.


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

1

Ist diese Frage noch offen für neue Vorschläge? Wenn ja, würde Ihnen das helfen?

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

Oh, und falls das C in Kleinbuchstaben umgewandelt werden muss:

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

Zur Übersicht:

$ 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

Was ist der Grund für die Verwendung '^C'?
— Edesz

1
^ bedeutet Zeilenanfang, andernfalls werden alle Vorkommen von C in Kleinbuchstaben umgewandelt ... sollte es welche geben

Ich muss hinzufügen, dass die anderen Vorschläge auch funktionieren. Viele Unix-Befehle können die gleiche Aufgabe übernehmen. Es liegt also an Ihnen, welchen Lösungsstil Sie bevorzugen.

Ich hatte vorher nicht danach gefragt ^, was hier auch in einigen anderen Antworten verwendet wurde. Danke für die Antwort und die Erklärung.
— Edesz
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.