Ruta de archivo de Windows convertida a ruta de archivo de Linux

13

Tengo una ruta de Windows en una variable bash como una cadena:

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

Estoy tratando de convertir esta ruta en una ruta de Linux a partir de /c/Users....

Mi intento

Los siguientes trabajos:

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

Problema

Aquí, he hecho esto para una cadena que contiene la ruta del archivo. La razón por la que hago esta pregunta es que tengo que convertir 20 cadenas de este tipo en un script bash en Ubuntu 16.04 y cada vez que hago esto tengo que escribir 2 líneas por conversión, ¡ocupa mucho espacio!

Pregunta

¿Hay alguna manera de combinar los 2 comandos?

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

en un comando?

edesz
fuente
1
Use un bucle for (y tal vez una matriz). También cita tus variables.
wjandrea
Gracias. ¿Podría mostrar un ejemplo de cómo hacer esto en un bucle o matriz?
edesz

Respuestas:

17

Habría una forma de hacer ambos reemplazos a la vez sed, pero no es necesario.

Así es como resolvería este problema:

  1. Poner nombres de archivo en la matriz
  2. Iterar sobre matriz

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

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

Si desea colocar el resultado en una matriz en lugar de imprimir, reemplace la echolínea con una asignación:

  filenames_out+=( "$f" )
wjandrea
fuente
Ok, pero si tuviera 2 archivos f1y f2, ¿cómo funcionaría? Quiero decir, ¿cómo puedo reasignar los nuevos nombres de archivo a la matriz reemplazando los antiguos?
edesz
@WR los puso en una nueva matriz y los usó.
muru
@WR agregó eso en la respuesta
wjandrea
1
Recomiendo hacer una nueva matriz, en aras de la claridad.
wjandrea 05 de
9

Si es algo que desea hacer muchas veces, ¿por qué no crear una pequeña función de shell?

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
conductor de acero
fuente
Esa no es una mala idea. Sin embargo, no parece dar /c/Users..., sino dar C:\Users\....
edesz
@WR disculpas - error de copiar y pegar. Por favor inténtalo ahora.
steeldriver
1
Gracias, lo uso cdw () { f="${1/D://d}"; cd "/mnt${f//\\//}"; }en el subsistema de Windows para Linux, ¡funciona de maravilla!
Fin de semana
2

Podrías lograr esto en una línea usando sed

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

Tenga en cuenta que los dos patrones deben permanecer separados, ya que las coincidencias se reemplazan por sustituciones diferentes.

taifwa
fuente
1
Sinónimo:file="$(sed 's|^C:|/c|; s|\\|/|g' <<< "$file")"
wjandrea
1

¿Esta pregunta aún está abierta a nuevas sugerencias? Si es así, ¿esto te ayudaría?

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

Ah, y en caso de que la C se convierta en minúsculas:

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

Como resumen:

$ 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

fuente
¿Cuál es la razón para usar '^C'?
edesz
1
^ significa el inicio de la línea, de lo contrario, todas las ocurrencias de C se pondrán en minúsculas ... si hubiera alguna
Debo agregar que las otras sugerencias también funcionan. Muchos comandos de Unix pueden hacer el mismo trabajo, así que depende de ti qué estilo de solución prefieras usar.
No había preguntado antes sobre ^eso, también se ha utilizado en algunas otras respuestas aquí. Gracias por la respuesta y la explicación.
edesz