Windows filepath converted to Linux filepath

23,114

Solution 1

There would be a way to do both replacements at once using sed, but it's not necessary.

Here's how I would solve this problem:

  1. Put filenames in array
  2. Iterate over array

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

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

If you want to put the output into an array instead of printing, replace the echo line with an assignment:

  filenames_out+=( "$f" )

Solution 2

If it's something you want to do many times, then why not create a little shell function?

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

Solution 3

You would be able to achieve this in one line using sed

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

Note the two patterns must remain separate nonetheless as the matches are replaced by different substitutions.

Solution 4

Is this question still open to new suggestions? If so, would this help you?

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

Oh, and in case the C must be cast to lowercase:

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

As an overview:

$ 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
Share:
23,114

Related videos on Youtube

edesz
Author by

edesz

Updated on September 18, 2022

Comments

  • edesz
    edesz over 1 year

    I have a Windows path in a bash variable as a string:

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

    I am trying to convert this path into a Linux path starting with /c/Users....

    My attempt

    The following works:

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

    Problem

    Here, I have done this for a string that contains the filepath. The reason I am asking this question is that I have to convert 20 such strings in a bash script in Ubuntu 16.04 and each time I do this I have to write 2 lines per conversion - it is taking up a lot of space!

    Question

    Is there a way to combine the 2 commands

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

    into one command?

    • wjandrea
      wjandrea about 7 years
      Use a for loop (and maybe an array). Also quote your variables.
    • edesz
      edesz about 7 years
      Thanks. Could you show an example of how to do this in a loop or array?
  • edesz
    edesz about 7 years
    That's not a bad idea. However, it does not seem to give /c/Users... - instead it is giving C:\Users\....
  • edesz
    edesz about 7 years
    Ok.But if I had 2 files f1 and f2, how would that work? I mean, how do I re-assign the new filenames to the array by replacing the old ones?
  • steeldriver
    steeldriver about 7 years
    @WR apologies - copy-paste error. Please try it now.
  • muru
    muru about 7 years
    @WR put em in a new array and use that.
  • wjandrea
    wjandrea about 7 years
    @WR Added that into the answer
  • wjandrea
    wjandrea about 7 years
    Synonym: file="$(sed 's|^C:|/c|; s|\\|/|g' <<< "$file")"
  • wjandrea
    wjandrea about 7 years
    I'd recommend to make a new array, for clarity's sake.
  • edesz
    edesz about 7 years
    What is the reason for using '^C'?
  • Admin
    Admin about 7 years
    ^ means start of the line, otherwise all occurences of C will become lowercase... should there be any
  • Admin
    Admin about 7 years
    I must add that the other suggestions also work. Many Unix command can do the same work, so its up to you what style of solution you prefer use.
  • edesz
    edesz about 7 years
    I had not asked earlier about ^ that has been used in some other answers here too. Thanks for the answer and the explanation.
  • Weekend
    Weekend about 6 years
    Thanks, I use cdw () { f="${1/D://d}"; cd "/mnt${f//\\//}"; } in Windows subsystem for Linux, works like a charm!