Search code examples
shellenvironment-variablesfish

Fail to set shell enviroment when part of value is empty on fish shell


I cannot set shell enviroment on fish shell. This seems to be a bug.

  • $LIBRARY_PATH is initiated to empty value.
  • Then append some value to $LIBRARY_PATH.
  • From $status I see the command is successfully executed.
  • But the result shows $LIBRARY_PATH is still empty.
⋊> /h/m/g/gcc-releases-gcc-9.2.0 echo $LIBRARY_PATH                                                                                                                                                                       (base) 00:09:23

⋊> /h/m/g/gcc-releases-gcc-9.2.0 set LIBRARY_PATH /usr/lib/x86_64-linux-gnu:$LIBRARY_PATH                                                                                                                                 (base) 00:09:25
⋊> /h/m/g/gcc-releases-gcc-9.2.0 echo $status                                                                                                                                                                             (base) 00:09:39
0
⋊> /h/m/g/gcc-releases-gcc-9.2.0 echo $LIBRARY_PATH                                                                                                                                                                       (base) 00:09:45

⋊> /h/m/g/gcc-releases-gcc-9.2.0
  • Then I set $LIBRARY_PATH to some value.
  • Append new values agian.
  • Script executed successfully.

In turn to prove my conclusion.

⋊> /h/m/g/gcc-releases-gcc-9.2.0 set LIBRARY_PATH /usr/lib/x86_64-linux-gnu                                                                                                                                               (base) 00:09:52
⋊> /h/m/g/gcc-releases-gcc-9.2.0 echo $LIBRARY_PATH                                                                                                                                                                       (base) 00:18:36
/usr/lib/x86_64-linux-gnu
⋊> /h/m/g/gcc-releases-gcc-9.2.0 set LIBRARY_PATH /usr/lib/x86_64-linux-gnu:$LIBRARY_PATH                                                                                                                                 (base) 00:18:53
⋊> /h/m/g/gcc-releases-gcc-9.2.0 echo $LIBRARY_PATH                                                                                                                                                                       (base) 00:18:57
/usr/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu

BTW my fish version is 2.3.1. Could someone tell me why pls?

⋊> /h/m/g/gcc-releases-gcc-9.2.0 fish --version                                                                                                                                                                           (base) 00:21:46
fish, version 2.3.1

Solution

  • Quote it:

    set LIBRARY_PATH /usr/lib/x86_64-linux-gnu:"$LIBRARY_PATH"
    # or
    set LIBRARY_PATH "/usr/lib/x86_64-linux-gnu:$LIBRARY_PATH"
    

    All fish variables are lists, and when it concatenates a list and some string it does so by combining all the list elements with the string:

    set list 1 2 3
    echo foo$list
    # prints 'foo1 foo2 foo3'
    

    Undefined variables are empty lists, so it combines the string with all zero elements, so the logical conclusion is nothing:

    set list
    echo foo$list
    # prints nothing
    

    This is quite useful when you do something like

    set dirs /home /bin /etc
    for file in $dirs/*
        echo $file
    end
    
    set dirs # $dirs is now empty
    for file in $dirs/*
        echo $file # does not run
    end
    

    because, when $dirs is empty, it does nothing instead of what bash would do which is run for file in /*, which is quite useless and potentially harmful (imagine rm -rf $dirs/*).

    To avoid this, you can double-quote the variable, in which case it expands to one string:

    set empty
    echo foo"$empty"
    # prints "foo"