Windows filepath converted to Linux filepath
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:
- Put filenames in array
- 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
Related videos on Youtube
edesz
Updated on September 18, 2022Comments
-
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 about 7 yearsUse a for loop (and maybe an array). Also quote your variables.
-
edesz about 7 yearsThanks. Could you show an example of how to do this in a loop or array?
-
-
edesz about 7 yearsThat's not a bad idea. However, it does not seem to give
/c/Users...
- instead it is givingC:\Users\...
. -
edesz about 7 yearsOk.But if I had 2 files
f1
andf2
, how would that work? I mean, how do I re-assign the new filenames to the array by replacing the old ones? -
steeldriver about 7 years@WR apologies - copy-paste error. Please try it now.
-
muru about 7 years@WR put em in a new array and use that.
-
wjandrea about 7 years@WR Added that into the answer
-
wjandrea about 7 yearsSynonym:
file="$(sed 's|^C:|/c|; s|\\|/|g' <<< "$file")"
-
wjandrea about 7 yearsI'd recommend to make a new array, for clarity's sake.
-
edesz about 7 yearsWhat is the reason for using
'^C'
? -
Admin about 7 years^ means start of the line, otherwise all occurences of C will become lowercase... should there be any
-
Admin about 7 yearsI 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 about 7 yearsI had not asked earlier about
^
that has been used in some other answers here too. Thanks for the answer and the explanation. -
Weekend about 6 yearsThanks, I use
cdw () { f="${1/D://d}"; cd "/mnt${f//\\//}"; }
in Windows subsystem for Linux, works like a charm!