3

In an attempt to dry up my bashrc, I tried changing this,

CDPATH=".:~/Development:~/Development/resources:~"

to this,

CDPATH=".:~/Development{,/resources}:~"

But I found the brace expansion wasn't performed inside the quoted string. Is there a way to achieve this?

  • Are you certain that ~ works? I know it doesn't work in quoted strings, nor after : even without quotes, but maybe CDPATH takes care of this for you. – Random832 May 27 '15 at 15:42
  • No, brace expansion will never work inside quotes. Quoting removes the special meaning of { and } and many other characters. That's the whole point of quoting. If you want the characters to have their special meanings, don't quote them. – Celada May 27 '15 at 16:07
  • 1
    @Random832 Bash expands ~ in PATH and CDPATH. In PATH, this is rather unhelpful because other applications do not expand ~ and so if you do this, you PATH entries that only apply when bash is the one doing the lookup. For CDPATH, it's only bash doing the lookup so that's ok. – Gilles May 27 '15 at 22:48
3

Yeah, actually there is:

set . ~/Development{,/resources} ~
IFS=:; CDPATH="$*"

The "$*" special parameter substitutes the first character in $IFS between each of the positional parameters. So if you set them and expand the arguments you want as separate arguments, you can then quickly fill in the appropriate delimiters as necessary on assignment.

If, as has been suggested might be the case, you could use some pointers on how to save/restore the value of $IFS, you might do the thing like:

CDPATH=$IFS
set . ~/Development{,/resources} ~
IFS=:${IFS+;IFS=\$CDPATH}
eval 'set "$*"; unset IFS'"
      $IFS;    CDPATH=\$1"

Sometimes a little juggle is worth it to keep the environment clean - and when a parameter affects the environment whether it is set or not - and in different ways depending - it probably is best to take care.

Still - such precautions are only really necessary in an environment in which you can guarantee no lasting control - in other words you don't need to do that in your own rc files. In a context like that you're pretty much guaranteed permanent control - and so you can (and should) set the special shell parameters to suit you.

  • 3
    Given that this is in response to a beginner shell scripting question, an answer that changes $IFS without restoring it is likely to cause more harm than good, and it would certainly cause issues if this snippet were incorporated into a larger script. I'd suggest editing this to at least save and restore IFS. – godlygeek May 27 '15 at 20:51
  • @godlygeek - done – mikeserv May 27 '15 at 21:50
  • 1
    Well, this is good to know, but since the complexity of the solution far outstrips the amount of duplication it would eliminate, I'll just stick with the hard-coded original :) – ivan May 28 '15 at 2:34
  • @ivan - I'm sorry if I gave you the wrong impression - the last bit there was intended to encourage you to do other than I demonstrated. In your rcfile you should be doing IFS='<space><tab><newline>' - or whatever you want it to be - anyway. In fact - that's probably something worth checking for in a prompt function even. So the top bit is really what you should do, but maybe add unset IFS to the end there, and maybe do something in your prompt or elsewhere that will reset $IFS to a sane value if it is detected to be unset - like PS1=${0##*["${PS1:= \t\n}$0"}$PS1 or something. – mikeserv May 28 '15 at 2:45

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.