22

I need to append a directory to PKG_CONFIG_PATH. Normally, I would use the standard

export PKG_CONFIG_PATH=${PKG_CONFIG_PATH}:$(pyenv prefix)/lib/pkgconfig

but PKG_CONFIG_PATH has not been previously set on my system. Therefore, the variable begins with a : character, which tells it to look in the current directory first. I do not want that. I settled on the following,

export PKG_CONFIG_PATH=${PKG_CONFIG_PATH}${PKG_CONFIG_PATH:+:}$(pyenv prefix)/lib/pkgconfig

but that just seems so ugly. Is there a better way? What is the appropriate way to conditionally append the colon if and only if the variable has already been set?

2

2 Answers 2

24

You are on the right track with the ${:+} expansion operator, you just need to modify it slightly:

V=${V:+${V}:}new_V

The first braces expand to $V and the colon iff V is set already otherwise to nothing - which is exactly what you need (and probably also one of the reasons for the existence of the operator).

Thus in your case:

export "PKG_CONFIG_PATH=${PKG_CONFIG_PATH:+${PKG_CONFIG_PATH}:}$(pyenv prefix)/lib/pkgconfig"
8
  • 2
    I was using that form, but I decided against it because it felt (slightly) less readable: ${V}${V:+:}W vs. ${V:+${V}:}W. Either way, they both feel really ugly. I was hoping for something... more elegant, I guess?
    – scottbb
    Oct 18, 2014 at 20:06
  • @scottbb - this is the syntax form - it is how it is done. If you want to set a variable's value based on a condition you have to do a test. You can do an inline test as is written here, or you can explicitly test with test - either way you're testing the value and writing the varname twice, but this way you do it in a single execution statement - in that way it is practical, but I've never met an elegant computer.
    – mikeserv
    Oct 18, 2014 at 20:18
  • @scottbb Thinking of it it really is the same. But I'm afraid you won't get it any better, since you basically need the variable name in the condition and then in the expansion - I don't think there is a shell construct that would do that with just one occurrence of the name.
    – peterph
    Oct 18, 2014 at 20:23
  • 1
    @mikeserv - I probably should have been more precise than to say I was looking for a more "elegant" solution. I have never really seen this done for appending substrings to PATH-style variables, and it felt somehow like I was missing a better way. In my experience, when I get that feeling, there usually is a better way. That's what I should have said. But your point is well taken. Thanks for your response. Also: in one of your edits of @peterph's comment, you made the comment that I should have quoted the entire argument to export. That's a very good point, I miffed that detail as well.
    – scottbb
    Oct 18, 2014 at 21:27
  • @scottbb - sorry if that came off as abrasive - ive never understood the concept of elegance with regards to computing. a computer is a machine - a three-way and/or gate compounded billions of times. it cant count higher than one - in every way, every thing it does is brute-forced. some intuitive concepts may be easier to translate than others, but, if so, it is only because the concept sits atop some other brute-forced abstraction. computing, at its heart, is always anything but elegant.
    – mikeserv
    Oct 18, 2014 at 21:41
1

Lately, I set up GNU stow on my machines to store user-wide stuff like libraries under ~/.local and ran into troubles when defining LD_LIBRARY_PATH, CPATH and LIBRARY_PATH, inadvertently putting a colon there and so breaking stuff.

Then I found your question and the answer wasn't exactly elegant ;-), and I wrote a small function to handle this, please find it here: https://gist.github.com/rico-chet/0229e4c080d9f51a02535dd25a656a8a

## Copyright (C) 2018 Alex Thiessen <[email protected]>
## Copyright (C) 2018 https://unix.stackexchange.com/users/116858/kusalananda
## SPDX-License-Identifier: GPL-2.0-or-later
## <https://spdx.org/licenses/GPL-2.0-or-later.html>

function join() {
    if [ ${#} -eq 0 ]
    then
        echo "\`join\` appends elements separated by colons to a \`bash\` variable " >&2
        echo "usage: join <variable> <element> [element ...]" >&2
        return 1
    fi
    variable="${1}"

    shift
    export ${variable}="${!variable:+${!variable}:}$(IFS=:; echo "${*}")"
}

// edited as suggested by @Kusalananda

6
  • Also: ( IFS=:; set -- 1 2 3 4 5 6; echo "$*" )
    – Kusalananda
    Jul 22, 2018 at 11:49
  • I.e.: join () { var=$1; shift; export "$var"="$( IFS=:; echo "$*" )"; }
    – Kusalananda
    Jul 22, 2018 at 12:37
  • ... Except that "join" is an unfortunate name as its also the name of a standard utility.
    – Kusalananda
    Jul 22, 2018 at 13:11
  • 1
    when the license is longer than the program ... : D
    – milahu
    Jan 29, 2022 at 16:51
  • 1
    Should I add a Code of Conduct, what do you think? ( ͡~ ͜ʖ ͡°)
    – Superlexx
    Feb 1, 2022 at 20:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .