Modern Bash Scripts

So far, this is just a short selection of items. I plan to convert this into a more elaborate form and provide examples sooner or later.


Bash has now many things built-in, that once required calling external commands. Most notably:

  • The testing of conditions used [...] which is just an alias for the program test. Just using [[...]] instead lets Bash evaluate the condition itself. This doesn't matter for single if statements, but complex scripts with loops experience a huge speed-up.
  • Simple calculation and string handling can be done by $(( 1 + I )) (instead of expr 1 + $I) and ${DIR/foo/bar} instead of calling sed.
  • Regular Expressions are build in (use [[...]])

Small bits and pieces


For an auto-generated TeX file, I want to automatically generate a CamelCase expression from filenames containing dashs and underlines. Many suggestions on the internet propose using sed or other secondary tools, but I tried to get it with Bash Buildins.

Bash has the parameter expansions ${parameter^pattern} and ${parameter,pattern} that convert the first matched character to upper or lower case. By setting the pattern to * or ?, the first letter of the variable $parameter is converted:

$ STR='abc def'
$ echo ${STR^?}
Abc def
$ echo ${STR^*}
Abc def
$ echo ${STR^^*}

There are variants with two ^^ or ,, that convert every occurence of a matched pattern. But how to convert only the first letter of every word? The solution is to use an array and apply the conversion to each element:

$ ARR=( $STR )
$ echo ${ARR[*]^*}
Abc Def

Back to the initial challenge: convert a string like my-filename_variant1. The approach is to convert the special characters to spaces and then tokenize the character string at word boundaries to an array.

$ TMP='my-filename_variant1'
$ TMP=${TMP//-/ }       # convert all '-' to spaces
$ TMP=${TMP//_/ }       # convert all '_' to spaces
$ TMP=( $TMP )          # tokeninze words to array
$ TMP=${TMP[*]^*}       # upper-case all words
$ TMP=${TMP// /}        # remove spaces
$ echo $TMP

There are probably more elegant ways with sed. I'm not sure, if it could be solved with Bash's regular expressions. And finally, I'm also not sure if this is still more efficient than a forked sed, but it is amazing what can be done with Bash alone.

Source: solved this problem with the creative help of Stackoverflow.