7

I'm new to shell scripting and trying to accomplish following, converting a windows path to a linux path and navigating to that location:

Input: cdwin "J:\abc\def" Action: cd /usr/abc/def/

So, I'm changing the following:

"J:" -> "/usr"

and

"\" -> "/"

This is my try, but it doesn't work. It just returns a blank if i echo it:

function cdwin(){
    line="/usrfem/Projects$1/" | sed 's/\\/\//g' | sed 's/J://'
    cd $line
}
jww
  • 97,681
  • 90
  • 411
  • 885
user2987193
  • 133
  • 1
  • 1
  • 7
  • 1
    2 consecutive sed seaprate by a pipe could often be done in 1 sed separate by a ";" ex: echo "/usrfem/Projects$1/" | sed 's|\\|/|g;s/J://' in yours case – NeronLeVelu Nov 15 '13 at 11:53

4 Answers4

11

You need to catch the variable and then process it.

For example this would make it:

function cdwin(){
    echo "I receive the variable --> $1"
    line=$(sed -e 's#^J:##' -e 's#\\#/#g' <<< "$1")
    cd "$line"
}

And then you call it with

cdwin "J:\abc\def"

Explanation

The command

line=$(sed -e 's#^J:##' -e 's#\\#/#g' <<< "$1")

is equivalent to

line=$(echo $1 | sed -e 's#^J:##' -e 's#\\#/#g')

and replaces every \ with /, saving the result into the var line. Note it uses another delimiter, #, to make it more readable. It also removes the leading J:.

fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • Change the replacement to this `line=$(sed -e 's#^\(.\):#/mnt/\L\1#' -e 's#\\#/#g' <<< "$1")` to make it work with WSL/Ubuntu on windows 10 for any drive and path – Vijay Sep 18 '18 at 16:13
  • When I run this code I get the error `-bash: cd: ~/work/projects: No such file or directory`, but if I manually run `cd ~/work/projects` from the command line, it works. Any idea what I'm doing wrong? – Josh Oct 30 '19 at 22:58
  • How to use the cdwin() ? Do I place it in .profile ? or do I need to create a file with the same name and do chmod +x and put the file in my PATH? – qqqqq Jul 29 '21 at 23:51
3

sed allows alternative delimiters so better to not to use /.

Try this sed command:

sed -e 's~\\~/~g' -e 's~J:~/usr~' <<< "$line"
anubhava
  • 761,203
  • 64
  • 569
  • 643
2

You don't even need to use sed (although there's nothing wrong with using sed). This works for me using bash string substitution:

function cdwin() {
  line=${1/J://usr}
  line=${line//\\//}
  cd "$line"
}

cdwin 'J:\abc\def'

Substitution works as follows (simplification):

${var/find/replace} 

and double slash means replace all:

${var//findall/replace}

In argument 1, replace the first instance of J: with /usr:

${1/J://usr}

In variable line replace all (//) backslashes (escaped, \\) with (/) forwardslash (/):

${line//\\//}

echo the output of any of those to see how they work

stu0292
  • 471
  • 4
  • 7
0

My code is inspired by the top post but modified to work with any drive on windows 10 while running on native ubuntu (aka WSL).

You can comment out the debugging lines if you just want the function.

You can comment out the cd line if you just want output path

function cdwin() {
    # Converts Windows paths to WSL/Ubuntu paths, prefixing /mnt/driveletter and preserving case of the rest of the arguments,
    # replacing backslashed with forwardslashes
    # example: 
    # Input -> "J:\Share"
    # Output -> "/mnt/j/Share"
    echo "Input --> $1" #for debugging
    line=$(sed -e 's#^\(.\):#/mnt/\L\1#' -e 's#\\#/#g' <<< "$1")
    #Group the first character at the beginning of the string. e.g. "J:\Share", select "J" by using () but match only if it has colon as the second character
    #replace J: with /mnt/j
    #\L = lowercase , \1 = first group (of single letter)
    # 2nd part of expression
    #replaces every \ with /, saving the result into the var line. 
    #Note it uses another delimiter, #, to make it more readable.
    echo "Output --> $line" #for debugging
    cd "$line" #change to that directory
}
Vijay
  • 891
  • 3
  • 19
  • 35