Windows shell lang neckbreak

Windows Shell Bug Now I have one very good reason to never install anything again in “Program Files (x86)” folder where 64-bit Windows XP usually puts 32-bit apps. The reason is closing bracket character “)” in path, which in combination with “special” behavior of windows cmd.exe shell can (and will) give you a lot of pain in the neck if you do shell scripting (under Win AKA batch scripting). And even if you don’t do shell scripting yourself, some shell scripts that you or any soft you use might need to run, may break.


Windows cmd.exe shell problems In my case it was setDomainEnv script for Weblogic Enterprice Application Server which is executed on server startup – it broke after setting JAVA_HOME variable value to a path C:\Program Files (x86)\Java\JDK1.5.0_21 , which was really not nice.

So, the core of the problem is that the cmd shell script interpreter can mix up brackets used for grouping statements and closing bracket in variables values.
For example:
> set VAR_A=ab^)cd
> echo %VAR_A%
ab)cd
> set VAR_B=%VAR_A%
> echo %VAR_B%
ab)cd
> if 1==1 ( set VAR_C=%VAR_A% )
cd was unexpected at this time.

Obviously during interpretation the line became “if 1==1 ( set VAR_C=ab)cd )” and execution threw syntax error. Making a batch file with “set VAR_C=%VAR_A%” on separate line doesn’t help.

Trying workaround:
> set VAR_C="%VAR_A%"
> echo %VAR_C%
"ab)cd"

Unnecessary quotes appear – not good. And we don’t want to update SETs in all scripts anyway.

That’s it for cmd.exe problem.
Rest of the story:

As I couldn’t waste much time on examining Win’s shell strangeness I had to fix problem other way, so I decided to make a hard link.

At that moment I forgot that short (8+3 character) DOS-compatible filenames are still generated for all my files and folders. But one may not be able to use short name instead of full name because though DOS-compatible filename is guaranteed not to contain some “fancy” chars like quotes braces and etc, brackets can still be there.

In my case short name was OK (brackets were at the end of title so they got cut off), so it could be used. But I also know that auto-generation of DOS-compatible filenames can be disabled, so maybe it won’t be available at all soon, and all in all hard links are more “progressive”. (BTW, I later googled-up an article that made me really wish to disable autogeneration of DOS-compatible filenames ASAP as it brought up some “nice” side-effects of double naming for files I haven’t thought about before (and most people never knew about I guess), but we’re getting off topic).

Thus I needed a hard link from c:\Java to c:\Program Files (x86)\Java so I didn’t have to include brackets in path.
Surprisingly it wasn’t that easy also – NTFS hard links which you can create with fsutil.exe are only for files. For folders you need to create a Junction, and Win XP by default doesn’t feature any utility which could do this (AFAIK).

So I’ve googled up some small GUI-ed utility to do hard links and junctions, but the junction it created somehow appeared to be dysfunctional – it only showed 1 level of files/folders in it, entering junction subfolders showed empty dirs. So I finally downloaded FAR and created junction in it with ALT+F6 *relieved sigh*

Summing up, windows shell interpreter is not a good one. And though this time I could work my problem around – as I had to put into shell variable a file path, and there are ways to have more than one path to same file – next time I (or someone else) may not be so lucky, in cases when there would really really be a need to put that closing bracket in shell variable for some purpose.

Advertisements

2 thoughts on “Windows shell lang neckbreak

  1. Halo :)

    I’ve found two solutions.
    The first one uses a trick which M$ calls “Delayed variables expansion” and works in a batch file or directly in command-line in case you started it with V:ON switch (i.e. cmd.exe /V:ON)

    SETLOCAL EnableDelayedExpansion
    SET VAR_A=ab^)cd
    SET VAR_B=%VAR_A%
    IF 1==1 (SET VAR_C=!VAR_A!)
    ECHO VAR_A = %VAR_A%
    ECHO VAR_B = %VAR_B%
    ECHO VAR_C = %VAR_C%
    ENDLOCAL
    ___________

    The second solution sets VAR_C using CALL statement and works only in the batch file:

    SET VAR_A=ab^)cd
    SET VAR_B=%VAR_A%
    IF 1==1 (CALL SET VAR_C=%%VAR_A%%)
    ECHO VAR_A = %VAR_A%
    ECHO VAR_B = %VAR_B%
    ECHO VAR_C = %VAR_C%

    • Thanks a lot Volodya for your reply.
      You have found _two_ solutions – wow! (-:
      This might come handy in future, so thanks again.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s