I want to modify the cygwin path to the windows path from within a makefile. For that purpose, I am using

CURDIR := `pwd`
WINDIR := $(shell echo $(CURDIR) | sed -e "s/\/cygdrive\/\(.\)/\1:/" | sed -e 's/\//\\/g')

When I execute this makefile using gnumake, i am faced with this error:

sed.exe: -e expression #1, char 8: Unterminated `s' command

However, when i execute the following command on the cygwin shell directly, I get the desired output:

$: pwd | sed -e "s/\/cygdrive\/\(.\)/\1:/" | sed -e 's/\//\\/g'

The above command works perfectly and there is no complaint from the shell of any sort. Why am I facing this issue and what could be a possible remedy?

  • I don't know cygwin, but you might try changing shell echo... to shell set -x; echo... so that you can see on stderr what command is being passed to the shell for execution. Add the output to your question. – meuh May 12 at 13:35
  • 1
    It seems you are trying to convert Cygwin's Linux path format to Windows'. If that is the case, please look into cygpath command with the --windows option. – Hai Vu May 12 at 13:46
  • Thanks for the tip Hai Vu. It worked and provided the result I was after. Thanks again – Saswata Banerjee May 12 at 18:50

To explain the problem you're seeing, it's happening in the second sed command:

sed -e 's/\//\\/g'

make uses \ as a special character that can be used to escape %, so \\ is an escape sequence that translates to \ (a single backslash.)

Other than two backslashes in a row or when followed by %, the backslash is preserved verbatim, so \/ is kept as \/ and won't cause any problems (that's why only this place caused trouble.)

So the sed command that actually gets executed is:

sed -e 's/\//\/g'

It's easier to see how this command is incomplete if you use a different delimiter, such as #:

sed -e 's#/#/g'

First off, the ending delimiter (in this case #) is missing. Furthermore, the replacement is getting a / and not a \ as intended.

You can fix it by adding an extra backslash (or two will also work):

sed -e 's/\//\\\/g'

But this might look quite odd to someone reading that code, so I'd recommend adding a comment to explain what is going on.

Another good idea would be to double every backslash, to make it clear that make is using one level of them as escape sequences:

sed -e 's/\\//\\\\/g'

Ugh, still pretty awful... Using a delimiter other than # might help a little bit, but probably not that much:

sed -e 's#/#\\\\#g'

For the specific case you're using sed here, which is to convert a Cygwin path to a Windows path, you can actually use cygpath --windows, as pointed out by @HaiVu in comments.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.