A thorough understanding of bash programming is vital when working with ebuilds.

Inside [ ] blocks, several -test style boolean operators are available. These should be avoided in favour of [[ ]] and the above operators.

Note: These will also sometimes work inside [[ ]] constructs, and using ! before a test is fairly common. [[ ! -f foo ]] && bar is fine. However, there are catches — [[ -f foo && bar ]] will not work properly, since commands cannot be run inside [[ ]] blocks.

There are constructs available for boolean algebra ('and', 'or' and 'not'). These are used outside of the [[ ]] blocks. For operator precedence, use ( ) .

The general form of a file comparison is "file1" -operator "file2" . The following are available (lifted from man bash ):

The general form of a file test is -operator "filename" . The following are available (lifted from man bash ):

The general form of integer comparisons is int1 -operator int2 . The following are available:

Note: To check whether a variable is set and not blank, use -n "${BLAH}" rather than -n $BLAH . The latter will cause problems in some situations if the variable is unset.

The general form of string tests is -operator "string" . The following are available:

The general form of a string comparison is string1 operator string2 . The following are available:

This is because [[ ]] is a bash syntax construct, whereas [ ] is a program which happens to be implemented as an internal — as such, cleaner syntax is possible with the former. For a simple illustration, consider:

Important: The [[ ]] form is generally safer than [ ] and should be used in all new code.

if [[ -z " ${foo} " ]] ; then die " Please set foo " fi if [[ " ${foo} " = = " moo " ]] ; then einfo " Hello Larry " fi if [[ -f " ${ROOT} /etc/deleteme " ]] ; then einfo " Please delete ${ROOT} /etc/readme manually! " fi

To do comparisons or file attribute tests, [ ] or [[ ]] blocks are needed.

if some_stuff ; then Do nothing : else einfo " Not some stuff " fi

If you really don't want to restructure the block, you can use a single colon ( : ) on its own as a null statement.

if some_stuff ; then A statement is required here. a blank or a comment isn't enough! else einfo " Not some stuff " fi

Warning: You must specify at least one statement inside each block. The following will not work:

if something ; then do_stuff elif something_else ; then do_other_stuff elif full_moon ; then howl else turn_into_a_newt fi

Multiple pronged selection can be done using else and elif :

See die and Subshells for an explanation of why while read < file should be used over cat file | while read .

while read myline ; do einfo " It says ${myline} " done < some_file

This is most commonly used to iterate over lines in a file:

There is also a while loop, although this is usually not useful within ebuilds.

There is a second form of the for loop which can be used for repeating an event a given number of times.

for myvar in " the first " " the second " " and the third " ; do einfo " This is ${myvar} " done

There are a few simple iterative structures available from within bash . The most useful of these is a for loop. This can be used to perform the same task upon multiple items.

Bash Variable Manipulation

There are a number of special ${} constructs in bash which either manipulate or return information based upon variables. These can be used instead of expensive (or illegal, if we're in global scope) external calls to sed and friends.

bash String Length The ${#somevar} construct can be used to obtain the length of a string variable. somevar = " Hello World " echo " ${somevar} is ${#somevar} characters long "

bash Variable Default Values There are a number of ways of using a default value if a variable is unset or zero length. The ${var:-value} construct expands to the value of ${var} if it is set and not null, or value otherwise. The ${var-value} construct is similar, but checks only that the variable is set. The ${var:=value} and ${var=value} forms will also assign value to var if var is unset (and also set, but null for the := form). The ${var:?message} form will display message to stderr and then exit if var is unset or null. This should generally not be used within ebuilds as it does not use the die mechanism. There is a ${var?message} form too. The ${var:+value} form expands to value if var is set and not null, or a blank string otherwise. There is a ${var+value} form.

bash Substring Extraction The ${var:offset} and ${var:offset:length} constructs can be used to obtain a substring. Strings are zero-indexed. Both offset and length are arithmetic expressions. The first form with a positive offset returns a substring starting with the character at offset and continuing to the end of a string. If the offset is negative, the offset is taken relative to the end of the string. Note: For reasons which will not be discussed here, any negative value must be an expression which results in a negative value, rather than simply a negative value. The best way to handle this is to use ${var:0-1} . ${var:-1} will not work. The second form returns the first length characters of the value of ${var} starting at offset . If offset is negative, the offset is taken from the end of the string. The length parameter must not be less than zero. Again, negative offset values must be given as an expression.

bash Command Substitution The $(command) construct can be used to run a command and capture the output ( stdout ) as a string. Note: The `command` construct also does this, but should be avoided in favour of $(command ) for clarity, ease of reading and nesting purposes. myconf = " $( use_enable acl ) $( use_enable nls ) --with-tlib=ncurses "

bash String Replacements There are three basic string replacement forms available: ${var#pattern} , ${var%pattern} and ${var/pattern/replacement} . The first two are used for deleting content from the start and end of a string respectively. The third is used to replace a match with different content. The ${var#pattern} form will return var with the shortest match of pattern at the start of the value of var deleted. If no match can be made, the value of var is given. To delete the longest match at the start, use ${var##pattern} instead. The ${var%pattern} and ${var%%pattern} forms are similar, but delete the shortest and longest matches at the end of var respectively. Note: The terms greedy and non-greedy are sometimes used here ( % and # being the non-greedy forms). This is arguably incorrect, but the terms are fairly close. The ${var/pattern/replacement} construct expands to the value of var with the first match of pattern replaced with replacement . To replace all matches, ${var//pattern/replacement} can be used. Note: man bash incorrectly describes what will be matched. Of all the possible leftmost matches, the longest will be taken. Yes, really, the longest, even if it involves favouring later groups or later branches. This is not like perl or sed . See incorrectly describes what will be matched. Of all the possible leftmost matches, the longest will be taken. Yes, really, the longest, even if it involves favouring later groups or later branches. This islikeor. See IEEE Std 1003.1-2017, section 9.1 for details. To match only if pattern occurs at the start of the value of var , the pattern should begin with a # character. To match only at the end, the pattern should begin with a % . If replacement is null, matches are deleted and the / following pattern may be omitted. The pattern may contain a number of special metacharacters for pattern matching. Todo: tables of bash metachars If the extglob shell option is enabled, a number of additional constructs are available. These can be extremely useful sometimes. Todo: table of extra bash goodies