Skip to content

all

L_lib.sh

globals

some global variables

$L_LIB_VERSION

Version of the library

$L_LIB_SCRIPT

The location of L_lib.sh file

$L_NAME

The basename part of $0.

$L_DIR

The directory part of $0.

colors

Variables storing xterm ANSI escape sequences for colors.

Variables with L_ANSI_ prefix are constant. Variables without L_ANSI_ prefix are set or empty depending on L_color_detect function. TheL_color_detect` function can be used to detect if the terminal and user wishes to have output with colors.

Example

echo "$L_RED""hello world""$L_RESET"

$L_BOLD

$L_BRIGHT

$L_DIM

$L_FAINT

$L_ITALIC

$L_STANDOUT

Standaout means italic font.

$L_UNDERLINE

$L_REVERSE

$L_CONCEAL

$L_HIDDEN

$L_CROSSEDOUT

$L_FONT0

$L_FONT1

$L_FONT2

$L_FONT3

$L_FONT4

$L_FONT5

$L_FONT6

$L_FONT7

$L_FONT8

$L_FONT9

$L_FRAKTUR

$L_DOUBLE_UNDERLINE

$L_NODIM

$L_NOSTANDOUT

$L_NOUNDERLINE

$L_NOREVERSE

$L_NOHIDDEN

$L_REVEAL

$L_NOCROSSEDOUT

$L_BLACK

$L_RED

$L_GREEN

$L_YELLOW

$L_BLUE

$L_MAGENTA

$L_CYAN

$L_LIGHT_GRAY

$L_DEFAULT

$L_FOREGROUND_DEFAULT

$L_BG_BLACK

$L_BG_BLUE

$L_BG_CYAN

$L_BG_GREEN

$L_BG_LIGHT_GRAY

$L_BG_MAGENTA

$L_BG_RED

$L_BG_YELLOW

$L_FRAMED

$L_ENCIRCLED

$L_OVERLINED

$L_NOENCIRCLED

$L_NOFRAMED

$L_NOOVERLINED

$L_DARK_GRAY

$L_LIGHT_RED

$L_LIGHT_GREEN

$L_LIGHT_YELLOW

$L_LIGHT_BLUE

$L_LIGHT_MAGENTA

$L_LIGHT_CYAN

$L_WHITE

$L_BG_DARK_GRAY

$L_BG_LIGHT_BLUE

$L_BG_LIGHT_CYAN

$L_BG_LIGHT_GREEN

$L_BG_LIGHT_MAGENTA

$L_BG_LIGHT_RED

$L_BG_LIGHT_YELLOW

$L_BG_WHITE

$L_COLORRESET

$L_RESET

L_color_enable

The L_ color variables are set to the ANSI escape sequences.

Arguments: Takes no arguments

L_color_disable

The L_ color variables are set to empty strings.

Arguments: Takes no arguments

L_term_has_color

Detect if colors should be used on the terminal.

Argument: [$1] file descriptor to check, default: 1

Uses environment variables:

  • TERM
  • NO_COLOR

Return: 0 if colors should be used, nonzero otherwise

See: https://no-color.org/

L_color_detect

Detect if colors should be used on the terminal.

Argument: [$1] file descriptor to check, default 1

Shellcheck disable= SC2120

See: https://en.wikipedia.org/wiki/ANSI_escape_code#Unix_environment_variables_relating_to_color_support

$L_ANSI_BOLD

$L_ANSI_BRIGHT

$L_ANSI_DIM

$L_ANSI_FAINT

$L_ANSI_STANDOUT

$L_ANSI_UNDERLINE

$L_ANSI_REVERSE

$L_ANSI_CONCEAL

$L_ANSI_HIDDEN

$L_ANSI_CROSSEDOUT

$L_ANSI_FONT0

$L_ANSI_FONT1

$L_ANSI_FONT2

$L_ANSI_FONT3

$L_ANSI_FONT4

$L_ANSI_FONT5

$L_ANSI_FONT6

$L_ANSI_FONT7

$L_ANSI_FONT8

$L_ANSI_FONT9

$L_ANSI_FRAKTUR

$L_ANSI_DOUBLE_UNDERLINE

$L_ANSI_NODIM

$L_ANSI_NOSTANDOUT

$L_ANSI_NOUNDERLINE

$L_ANSI_NOREVERSE

$L_ANSI_NOHIDDEN

$L_ANSI_REVEAL

$L_ANSI_NOCROSSEDOUT

$L_ANSI_BLACK

$L_ANSI_RED

$L_ANSI_GREEN

$L_ANSI_YELLOW

$L_ANSI_BLUE

$L_ANSI_MAGENTA

$L_ANSI_CYAN

$L_ANSI_LIGHT_GRAY

$L_ANSI_DEFAULT

$L_ANSI_FOREGROUND_DEFAULT

$L_ANSI_BG_BLACK

$L_ANSI_BG_BLUE

$L_ANSI_BG_CYAN

$L_ANSI_BG_GREEN

$L_ANSI_BG_LIGHT_GRAY

$L_ANSI_BG_MAGENTA

$L_ANSI_BG_RED

$L_ANSI_BG_YELLOW

$L_ANSI_FRAMED

$L_ANSI_ENCIRCLED

$L_ANSI_OVERLINED

$L_ANSI_NOENCIRCLED

$L_ANSI_NOFRAMED

$L_ANSI_NOOVERLINED

$L_ANSI_DARK_GRAY

$L_ANSI_LIGHT_RED

$L_ANSI_LIGHT_GREEN

$L_ANSI_LIGHT_YELLOW

$L_ANSI_LIGHT_BLUE

$L_ANSI_LIGHT_MAGENTA

$L_ANSI_LIGHT_CYAN

$L_ANSI_WHITE

$L_ANSI_BG_DARK_GRAY

$L_ANSI_BG_LIGHT_BLUE

$L_ANSI_BG_LIGHT_CYAN

$L_ANSI_BG_LIGHT_GREEN

$L_ANSI_BG_LIGHT_MAGENTA

$L_ANSI_BG_LIGHT_RED

$L_ANSI_BG_LIGHT_YELLOW

$L_ANSI_BG_WHITE

$L_ANSI_COLORRESET

It resets color and font.

$L_ANSI_RESET

ansi

Very basic functions for manipulating cursor position and color.

Note

unstable

L_ansi_up

L_ansi_down

L_ansi_right

L_ansi_left

L_ansi_next_line

L_ansi_prev_line

L_ansi_set_column

L_ansi_set_position

L_ansi_set_title

$L_ANSI_CLEAR_SCREEN_UNTIL_END

$L_ANSI_CLEAR_SCREEN_UNTIL_BEGINNING

$L_ANSI_CLEAR_SCREEN

$L_ANSI_CLEAR_LINE_UNTIL_END

$L_ANSI_CLEAR_LINE_UNTIL_BEGINNING

$L_ANSI_CLEAR_LINE

$L_ANSI_SAVE_POSITION

$L_ANSI_RESTORE_POSITION

L_ansi_print_on_line_above

Move cursor $1 lines above, output second argument, then move cursor $1 lines down.

Arguments:

  • $1 int lines above
  • $2 str to print

L_ansi_8bit_fg

L_ansi_8bit_bg

L_ansi_8bit_fg_rgb

Set foreground color to 8bit RGB

Arguments:

  • $1 red
  • $2 green
  • $3 blue

L_ansi_8bit_bg_rgb

Set foreground color to 8bit RGB

Arguments:

  • $1 red
  • $2 green
  • $3 blue

L_ansi_24bit_fg

Set foreground color to 24bit RGB

Arguments:

  • $1 red
  • $2 green
  • $3 blue

L_ansi_24bit_bg

Set background color to 24bit RGB

Arguments:

  • $1 red
  • $2 green
  • $3 blue

has

Set of integer variables for checking if Bash has specific feature.

$L_BASH_VERSION

Bash version expressed as a hexadecimal integer variable with digits 0xMMIIPP, where MM is major part, II is minor part and PP is patch part of version.

Shellcheck disable= SC2004

$L_HAS_BASH5_3

$L_HAS_BASH5_2

$L_HAS_BASH5_1

$L_HAS_BASH5_0

$L_HAS_BASH4_4

$L_HAS_BASH4_3

$L_HAS_BASH4_2

$L_HAS_BASH4_1

$L_HAS_BASH4_0

$L_HAS_BASH3_2

$L_HAS_BASH3_1

$L_HAS_BASH3_0

$L_HAS_BASH2_5

$L_HAS_BASH2_4

$L_HAS_BASH2_3

$L_HAS_BASH2_2

$L_HAS_BASH2_1

$L_HAS_BASH2_0

$L_HAS_BASH1_14_7

$L_HAS_TRAP_P

trap has -P option

$L_HAS_COMPGEN_V

`compgen' has a new option: -V varname. If supplied, it stores the generated

$L_HAS_NO_FORK_COMMAND_SUBSTITUTION

New form of command substitution: ${ command; } or ${|command;} to capture

$L_HAS_PATSUB_REPLACEMENT

New shell option: patsub_replacement. When enabled, a `&' in the replacement

$L_HAS_k_EXPANSION

There is a new parameter transformation operator: @k. This is like @K, but

$L_HAS_SRANDOM

SRANDOM: a new variable that expands to a 32-bit random number

$L_HAS_WAIT_P

wait: has a new -p VARNAME option, which stores the PID returned by `wait -n'

$L_HAS_UuLK_EXPASIONS

New U',u', and `L' parameter transformations to convert to uppercas New `K' parameter transformation to display associative arrays as key-

$L_HAS_EPOCHREALTIME

There is an EPOCHREALTIME variable, which expands to the time in seconds

$L_HAS_QEPAa_EXPANSIONS

There is a new ${parameter@spec} family of operators to transform the value of `parameter'.

$L_HAS_LOCAL_DASH

Bash 4.4 introduced function scoped local -

$L_HAS_MAPFILE_D

The `mapfile' builtin now has a -d option

$L_HAS_DECLARE_WITH_NO_QUOTES

The declare builtin no longer displays array variables using the compound

assignment syntax with quotes; that will generate warnings when re-used as input, and isn't necessary. Declare -p on Bash<4.4 adds extra $'\001' before $'\001' and $'\177' bytes.

$L_HAS_WAIT_N

The wait' builtin has a new-n' option to wait for the next child to

$L_HAS_NAMEREF

Bash 4.3 introduced declare -n nameref

$L_HAS_PRINTF_T

The printf builtin has a new %(fmt)T specifier

$L_HAS_VARIABLE_FD

If the optional left-hand-side of a redirection is of the form {var},

$L_HAS_EXTGLOB_IN_TESTTEST

Force extglob on temporarily when parsing the pattern argument to

the == and != operators to the [[ command, for compatibility.

$L_HAS_TEST_V

Bash 4.1 introduced test/[/[[ -v variable unary operator

$L_HAS_PRINTF_V_ARRAY

`printf -v' can now assign values to array indices.

$L_HAS_ASSOCIATIVE_ARRAY

Bash 4.0 introduced declare -A var=([a]=b)

$L_HAS_MAPFILE

Bash 4.0 introduced mapfile

$L_HAS_READARRAY

Bash 4.0 introduced readarray

$L_HAS_CASE_FALLTHROUGH

Bash 4.0 introduced case fallthrough ;& and ;;&

$L_HAS_LOWERCASE_UPPERCASE_EXPANSION

Bash 4.0 introduced ${var,,} and ${var^^} expansions

$L_HAS_BASHPID

Bash 4.0 introduced BASHPID variable

$L_HAS_COPROC

Bash 3.2 introduced coproc

$L_HAS_UNQUOTED_REGEX

[[ =~ has to be quoted or not, no one knows.

Bash4.0 change: The shell now has the notion of a compatibility level', controlled by new variables settable byshopt'. Setting this variable currently restores the bash-3.1 behavior when processing quoted strings on the rhs of the =~' operator to the[[' command. Bash3.2 change: Quoting the string argument to the [[ command's =~ operator now forces string matching, as with the other pattern-matching operators.

$L_HAS_PREFIX_EXPANSION

Bash 2.4 introduced ${!prefix*} expansion

$L_HAS_HERE_STRING

Bash 2.05 introduced <<<"string"

$L_HAS_INDIRECT_EXPANSION

Bash 2.0 introduced ${!var} expansion

$L_HAS_ARRAY

Bash 1.14.7 introduced arrays

Bash 1.14.7 also introduced: New variables: DIRSTACK, PIPESTATUS, BASH_VERSINFO, HOSTNAME, SHELLOPTS, MACHTYPE. The first three are array variables.

assert

L_panic

Print stacktrace and the message to stderr and exit with 249.

Example

[[ -r "$file" ]] || L_panic "File is not readable: $file"

Option: -[0-9]+ Exit with this number.

Argument: $@ Message to print.

See:

L_assert

Assert the command succeeds.

Execute a command given from the second positional argument. When the command fails, execute L_panic. Note: [[ is a bash syntax sugar and is not a command. ! is also not a standalone command or builtin, so it can't be used with this function. You could use eval "[[ ${var@Q} = ${var@Q} ]]". However to prevent quoting issues it is simpler to use wrapper functions. The function L_regex_match L_glob_match L_not are useful for writing assertions. To invert the test use L_not which just executes ! "$@".

Example

  L_assert 'wrong number of arguments' [ "$#" -eq 0 ]
  L_assert 'first argument must be equal to insert' test "$1" = "insert
  L_assert 'var has to match regex' L_regex_match "$var" ".*test.*"
  L_assert 'var has to not match regex' L_not L_regex_match "$var" "[yY][eE][sS]"
  L_assert 'var has to matcha glob' L_glob_match "$var" "*glob*"

Arguments:

  • $1

    str Assertion description.

    If the description starts with '-[0-9]+', the number is used as the exit code for L_panic.

  • $@ command to test

L_die

Print the arguments to standard error and exit wtih 248.

Example

test -r file || L_die "File is not readable"

Option: -[0-9]+ Exit with this number.

See:

L_exit

With no arguments or an empty string, exit with 0.

Otherwise, the arguments are printed to stderr and exit with 247.

Note

If you want to exit with number, just call builtin exit,

Example

    err=()
    test -r file || err+=("file is not readable")
    test -f file || err+=("file is not a file")
    L_exit "${err[@]}"

See:

L_check

Execute a command given from the second argument. If the command fails, call L_exit. The difference to L_assert is that it prints calltrace on error. L_check function only prints the error message with the program name on error.

See:

func

Function for writing function programs.

L_func_comment

Extract the comment above the function.

By default, get the comment of the calling function.

Example

   # some unrelated comment followed by an empty line

   # some comment
   somefunc() {
      L_func_comment
   }

   somefunc  # outputs '# some comment'

   L_func_comment -f somefunc

Options:

  • -v <var> Assign result to this variable.
  • -f <funcname> Print the comment of given function instead of the calling function.
  • -s <int> Consider the calling function this many stackframes above. Default: 0
  • -b Use Bash, do not use sed. For testing.
  • -h Print this help and return 0.

Return: 0 if extracted an non-empty comment above the function definition.

L_func_help

Print function comment as usage message.

:

   # @option -t this is an option
   # @option -g <arg> this is an option with an argument
   # @option -h Print this help and return 0.
   # @arg arg This is an argument
   utility() {
     local OPTIND OPTARG OPTERR opt t g
     while getopts tg:h opt; do
       case "$opt" in
         t) t=1 ;;
         g) g=$OPTARG ;;
         h) L_func_help; return 0 ;;
         *) L_func_usage; return 2 ;;
       esac
     done
     shift "$((OPTARG-1))"
     L_func_assert "one positional argument required" test "$#" -eq 1 || return 2
     #
     : utility logic
   }

   utility -h        # prints the comment above the function
   utility -invalid  # prints 'Usage: utility [-th] [-g arg] arg'

Argument: [int] How many stack frames up.

Return: 0

See:

L_func_usage

Print funtion usage to stderr.

Argument: [$1] How many stack frames up.

L_func_error

Print function error to stderr.

Arguments:

  • [$1] Message.
  • [$2] How many stack frames up.

See: L_func_help for example

L_func_usage_error

Print function error with usage.

Arguments:

  • [$1] Message.
  • [$2] How many stack frames up.

See: L_func_help for example

L_func_assert

Assert that the command exits with 0.

If it does not, call L_func_error and return 2. If the message starts with -[0-9]+, the number is used as the number of stackframes up the message is about.

Example

   utility() {
     local num="$1"
     L_func_assert "not a number: $num" L_is_integer "$num" || return 2
   }

Arguments:

  • $1 Message to print, may be empty.
  • $@ Arguments to test.

Return: 2 if the expression failed.

L_func_log

Print a line prefixed by the calling function name.

Argument: $@ line to print

L_function_copy

Make a copy of a function.

Currently there is no sanitization done in the function. The second argument allows for execution under eval.

Arguments:

  • $1 existing function
  • $2 new function name

L_function_modify

Add a script on the top or the end of a function.

Arguments:

  • $1 The function to modify
  • $2 Script to put in front of the function body.
  • $3 Script to put on the end of the function body.

L_decorate

Apply a decorator on a function.

The next call on a function will call the decorator with arguments followed by function name with arguments.

Example

    func() { echo something; }
    print_and_call() {
        echo "CALLING: $@" >&2
        "$@"
    }
    func  # outputs something
    func  # outputs something
    L_decorate print_and_call func
    func  # outputs "CALLING func" and then "something"
    func  # outputs "CALLING func" and then "something"

Example

    func() { L_print_traceback; }
    L_decorate L_setx func
    L_decorate time func
    L_decorate L_setx time func
    func arg  # calls: [L_setx time func arg]
              # which calls [time func arg]
              # which calls L_setx func arg

Arguments:

  • $@ Decorator to apply with arguments.
  • $#-1 Function.

L_time

Measure time with the command, but include the command in the time message output and use %6l format.

Argument: $@ command to measure.

L_duration_to_usec

Parse 1w1d1h2m2s into number of microseconds.

Option: -v <var>

Argument: $1 Duration string.

See: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#configuration-file

L_duration_to_usec_v

L_cache

Cache the execution of a command.

The command execution is cached in _L_CACHE global variable or in file when -f option is present. The second execution of the command will result in a cached execution. On cached execution the exit status of the command will be extracted from the cache.

Example

   L_cache -T 10m -O output -f /tmp/cache.L_cache curl -sS https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html

   myfunc() {
      var=$(( 1 + 2 ))
   }
   L_decorate L_cache -v var -k myfunc myfunc
   myfunc
   myfunc

Options:

  • -o

    Cache the stdout of the command.

           It will run the command in a process substitution.
    
  • -O <var>

    Cache the stdout of the command and store it in variable instead of printing.

           It will run the command in a process substitution.
    
  • -s <var> Add this variable to the cache. All cache variables will be restored on cached execution.
  • -f <file>

    Use the file as cache.

           The file has a header with version number.
           The file stores internal cache state from declare -p _L_cache variable.
           The file content is eval-ed upon loading.
    
  • -r Instead of executing, remove the cache entry associated with the command.
  • -l Instead of executing, only list the entires in the cache.
  • -T <ttl> Set time to live in duration string. Default: infinity.
  • -L <01> Lock the file with flock. Default: use flock if available.
  • -k <key> Use this key to index the cache. Default: %q quoted command with argumnets.
  • -h Print this help and return 0.

Arguments:

  • $1 Command to execute.
  • $@ Arguments.

Sets variable: _L_CACHE

Uses environment variable: _L_CACHE

Shellcheck disable= SC2094

Return:

222 on internal error

    otherwise returns the exit status of the cached command.

L_handle_v_scalar

Wrapper function for handling -v arguments to other functions.

It calls a function called <caller>_v with arguments, but without -v <var>. The function <caller>_v should set the variable nameref L_v to the returned value. When the caller function is called without -v, the value of L_v is printed to stdout with a newline. Otherwise, the value is a nameref to user requested variable and nothing is printed.

The fucntion L_handle_v_scalar handles only scalar value of L_v or 0-th index of L_v array. To assign an array, prefer L_handle_v_array.

:

   L_hello() { L_handle_v_arr "$@"; }
   L_hello_v() { L_v="hello world"; }
   L_hello          # outputs 'hello world'
   L_hello -v var   # assigns var="hello world"

Option: -v <var> Store the output in variable instead of printing it.

Argument: $@ arbitrary function arguments

Shellcheck disable= SC2317

Exit: Whatever exitcode does the <caller>_v funtion exits with.

See: L_handle_v_array

L_handle_v_array

Version of L_handle_v_scalar for arrays.

The options and arguments and exitcode is the same as L_handle_v_scalar.

This additionally supports assignment to arrays. This is not possible with L_handle_v_scalar.

The function L_handle_v_scalar is slightly faster and uses printf -v to assign the result. On newer Bash, printf -v can assign to array and associative arrays variable indexes.

In constract, L_handle_v_array has to first assert if the string is a valid variable name. Only then it uses eval with an array assignment syntax to assign the result to the user requsted variable.

Currently array indexes are not preserved. This could be worked on in the future when needed.

:

   L_hello() { L_handle_v_arr "$@"; }
   L_hello_v() { L_v=(hello world); }
   L_hello          # outputs two lines 'hello' and 'world'
   L_hello -v var   # assigns var=(hello world)

Shellcheck disable= SC2317

See: L_handle_v_scalar.

stdlib

Some base simple definitions for every occasion.

L_regex_match

Wrapper around =~ for contexts that require a function.

Arguments:

  • $1 string to match
  • $2 regex to match against

L_regex_escape

Produce a string that is a regex escaped version of the input.

Works for both basic and extended regular expression.

Option: -v <var> Store the output in variable instead of printing it.

Argument: $@ string to escape

See:

L_regex_escape_v

L_regex_findall

Get all matches of a regex to an array.

Option: -v <var> Store the output in variable instead of printing it.

Arguments:

  • $1 string to match
  • $2 regex to match

L_regex_findall_v

L_regex_replace

Replace all matches of a regex with a string.

In a string replace all occurences of a regex with replacement string. Backreferences like \& \1 \2 etc. are replaced in replacement string unless -B option is used. Written pure in Bash. Uses [[ =~ operator in a loop.

Example

  L_regex_replace -v out 'world world' 'w[^ ]*' 'hello'
  echo "$out"

Options:

  • -v <var> Store the output in variable instead of printing it.
  • -g Global replace
  • -c <int> Limit count of replacements, default: 1
  • -n <var> Variable to set with count of replacements made.
  • -B Do not handle backreferences in replacement string \& \1 \2 \
  • -h Print this help and return 0.

Arguments:

  • $1 string to match
  • $2 regex to match
  • $3 replacement string

Exit: If -n option is given, exit with 0, otherwise exit with 0 if at least one replacement was made, otherwise exit with 1.

L_execute

Executes the command.

Argument: $@ Command to execute.

L_not

Inverts exit status.

Argument: $@ Command to execute.

L_return

Return the first argument

Argument: $1 integer to return

L_shopt_extglob

Runs the command with extglob restoring the option after return.

Argument: $@ Command to execute

L_setx

Runs the command under set -x restoring the setting after return.

Argument: $@ Command to execute

L_unsetx

Runs the command under set +x restoring the setting after return.

Argument: $@ Command to execute

See: L_setx

L_setposix

Runs the command under set -o posix restoring the setting after return.

Argument: $@ Command to execute

L_unsetposix

Runs the command under set +o posix restoring the setting after return.

Argument: $@ Command to execute

L_glob_match

Wrapper around == for contexts that require a function.

Arguments:

  • $1 string to match
  • $2 glob to match against

Shellcheck disable= SC2053

See: L_extglob_match

L_extglob_match

Wrapper around == for contexts that require a function.

This is equal to L_glob_match when == has always extglob enabled. However, this was not the case for older bash. In which case this function temporary enables extglob.

Arguments:

  • $1 string to match
  • $2 glob to match against

Shellcheck disable= SC2053

See: L_glob_match

L_glob_escape

Produce a string that is a glob escaped version of the input.

Option: -v <var> Store the output in variable instead of printing it.

Argument: $@ string to escape

L_glob_escape_v

L_source

Execute source with arguments.

This is usefull when wanting to source a script without passing a arguments.

Arguments:

  • $1 Script to source.
  • $@ Positional arguments to script.

Shellcheck disable= SC1090

See: https://stackoverflow.com/a/73791073/9072753

L_eval

Evaluate the expression by first setting the arguments.

This is usefull to properly quote the expression and still use eval and variables.

Example

   L_assert 'variable has quotes' L_eval '[[ "$1" != *\"* ]]' "$variable"
   # much simpler and easier to quote than:
   L_assert 'variable has quotes' "[[ ${variable@Q} == *\\\"* ]]"

Arguments:

  • $1 Script to execute.
  • $@ Positional arguments to set for the duration of the script.

L_subshell

Call the command in a subshell.

Argument: $@ Command to excute.

L_compgen

Wrapper around compgen that does not support -V argument.

Note

copmgen -W allows execution. For example `compagen -W '$(echo something >&2)'`` executes echo.

Option: -V <var> Store the output in variable instead of printing it.

Argument: $@ Any other compgen options and arguments.

L_function_exists

Return 0 if the argument is a function

Argument: $1 function name

L_command_exists

Return 0 if the argument is a command.

Consider using L_hash instead. This differs from L_hash in the presence of an alias. command -v detects aliases. hash detects actual executables in PATH and bash functions.

Argument: $@ commands names to check

See: L_hash

L_hash

Execute Bash hash builtin with silenced output.

A typical mnemonic to check if a command exists is if hash awk 2>/dev/null. This saves to type the redirection.

Why hash and not command or type? Bash stores all executed commands from PATH in hash. Indexing it here, makes the next call faster.

Argument: $@ commands to check

See: L_command_exists

L_is_main

Return 0 if current script is not sourced.

L_is_sourced

Return 0 if current script sourced.

Comparing BASH_SOURCE to $0 only works, when BASH_SOURCE is different from $0. When calling . or source builtin it will be added as an "source" into FUNCNAME array. This function returns false, if there exists a source element in FUNCNAME array.

L_has_sourced_arguments

Return true if sourced script was passed any arguments.

When you source a script and do not pass any arguments, the arguments are equal to the parent scope.

$ set -- a b c ; source <(echo 'echo "$@"')          # script sourced with no arguments
a b c
$ set -- a b c ; source <(echo 'echo "$@"') d e f    # script sourced with arguments
d e f

It is hard to detect if the script arguments are real arguments passed to source command or not. This function detect the case by checking for a command "source" in FUNCNAME.

Example

   if L_is_main; then
      main
      exit $?
   elif L_has_sourced_arguments; then
      sourced_main "$@"
      return "$?"
   else
      sourced_main
      return "$?"
   fi

Arguments: Takes no arguments

See:

L_is_in_bash

Return 0 if running in bash shell.

Portable with POSIX shell.

L_in_posix_mode

Return 0 if running in posix mode.

L_var_is_set

Return 0 if variable is set

Argument: $1 variable nameref

Exit: 0 if variable is set, nonzero otherwise

L_var_is_notnull

Return 0 if variable is set and is not null (not empty)

Argument: $1 variable nameref

Exit: 0 if variable is set, nonzero otherwise

L_var_to_string

Serialize variable value to a string that can be declared.

The result is a string that is the value of variable quoted in a format that can be reused as input to declare.

For scalar variables, the function outputs a quoted value of the variable. For array and associative array variables, the function outputs a string in the form of ([a]=b) that can be used to assign to another variable.

Use declare with -a or -A for arrays to load the result into a variable. Eval is not preferred and might result in in valid values on Bash<4.4. Bash<4.4 prepends byte 0x01 in front of bytes 0x01 and 0x7f. Single 0x01 in declare -p output results in double 0x01,0x01.

Example

   local -A map=([a]=b [c]=d)
   L_var_to_string -v tmp map
   declare -A map2=$tmp

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 variable name

See:

L_var_is_notarray

Return 0 if variable is not an array neither an associative array.

Argument: $1 variable nameref

L_var_is_array

Return 0 if variable is an indexed integer array, not an associative array.

Argument: $1 variable nameref

L_var_is_associative

Return 0 if variable is an associative array.

Argument: $1 variable nameref

L_var_is_readonly

Return 0 if variable is readonly.

Argument: $1 variable nameref

L_var_is_integer

Return 0 if variable has integer attribute set.

Argument: $1 variable nameref

L_var_is_exported

Return 0 if variable is exported.

Argument: $1 variable nameref

L_var_to_string_v

L_printf_append

Append to the first argument if first argument is not null.

If first argument is an empty string, print the line. Used by functions optically taking a -v argument or printing to stdout, when such functions want to append the printf output to a variable for example in a loop or similar.

Example

  func() {
    local var=
    if [[ "$1" == -v ]]; then
       var=$2
       shift 2
    fi
    L_printf_append "$var" "%s" "Hello "
    L_printf_append "$var" "%s" "world\n"
  }
  func          # prints hello world
  func -v var   # stores hello world in $v

Arguments:

  • $1 variable to append to or empty string
  • $2 printf format specification
  • $@ printf arguments

Shellcheck disable= SC2059 SC2059

$L_NICE

An array to execute a command nicest way possible.

Example

"${L_NICE[@]}" make -j $(nproc)

L_nice

execute a command in nicest possible way

Argument: $@ command to execute

L_renice

Make the command be nicest possible.

Argument: [$1] Pid of the process. Default: $BASHPID.

L_show_nice

Show niceness levels of a process.

Argument: [$1] Pid of the process. Default: $BASHPID

L_sudo

Execute a command with sudo if not root, otherwise just execute the command.

Preserves all proxy environment variables.

L_uuid4

Generate uuid in bash.

Option: -v <var> Store the output in variable instead of printing it.

See: https://digitalbunker.dev/understanding-how-uuids-are-generated/

L_uuid4_v

L_date

Print date in the format.

If the format string contains %N or the timepoint is not a number, use date command. Otherwise, try to use printf %(fmt)T.

Options:

  • -v <var> Store the output in variable instead of printing it.
  • -h Print this help and exit.

Arguments:

  • $1 Format string.
  • [$2] Optional timepoint.

L_date_v

L_epochrealtime_usec

Return time in microseconds.

The dot or comma is removed from EPOCHREALTIME. Uses EPOCHREALTIME in newer Bash. In older Bash tries GNU date, gdate, perl, /proc/uptime, python, busybox adjtimex.

Option: -v <var>

L_epochrealtime_usec_v

L_sec_to_usec

Convert float seconds to microseconds.

Example

L_sec_to_usec 1.5 -> 1500000

Option: -v <var>

L_sec_to_usec_v

L_usec_to_sec

Convert microseconds to seconds with 6 digits after comma.

Option: -v <var>

L_usec_to_sec_v

L_timeout_set_to

Calculate timeout value.

The timeout value is stored in microseconds.

Note

should this be L_timeout_assign -v ?

Arguments:

  • $1 Variable to assign with the timeout value in usec.
  • $2 Timeout in seconds. May be a fraction.

See: L_epochrealtime_usec

L_timeout_expired

Is the timeout expired?

Argument: $1 timeout value

L_timeout_left

Get the number of seconds left in the timer.

Option: -v <var>

Argument: $1 timeout value

L_timeout_left_v

exit_to

L_exit_to

store exit status of a command to a variable

Arguments:

  • $1 variable
  • $@ command to execute

L_exit_to_1null

convert exit code to the word yes or to nothing

Example

    L_exit_to_1null suceeded test "$#" = 0
    echo "${suceeded:+"SUCCESS"}"  # prints SUCCESS or nothing

Arguments:

  • $1 variable
  • $@ command to execute

L_exit_to_1unset

convert exit code to the word yes or to unset variable

Example

    L_exit_to_1null suceeded test "$#" = 0
    echo "${suceeded:+"SUCCESS"}"  # prints SUCCESS or nothing

Arguments:

  • $1 variable
  • $@ command to execute

L_exit_to_10

store 1 if command exited with 0, store 0 if command exited with nonzero

Arguments:

  • $1 variable
  • $@ command to execute

path

L_path_basename

The filename

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 path

L_path_basename_v

L_path_dirname

parent of the path

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 path

L_path_dirname_v

L_path_extension

The last dot-separated portion of the final component, if any.

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 path

See: https://en.cppreference.com/w/cpp/filesystem/path/extension.html

L_path_extension_v

L_path_extensions

A list of the path’s suffixes, often called file extensions.

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 path

See: https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.suffixes

L_path_extensions_v

L_path_stem

The final path component, without its suffix:

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 path

See: https://en.cppreference.com/w/cpp/filesystem/path/stem

L_path_stem_v

L_path_with_name

Return a new path with the name changed.

Option: -v <var> Store the output in variable instead of printing it.

Arguments:

  • $1 path
  • $1 new name

L_path_with_name_v

L_path_with_stem

Return a new path with the stem changed.

Option: -v <var> Store the output in variable instead of printing it.

Arguments:

  • $1 path
  • $2 new stem

L_path_with_stem_v

Shellcheck disable= SC2179

L_path_with_suffix

Return a new path with the suffix changed.

Option: -v <var> Store the output in variable instead of printing it.

Arguments:

  • $1 path
  • $2 new suffix

L_path_with_suffix_v

Shellcheck disable= SC2179

L_path_is_absolute

Return whether the path is absolute or not.

L_path_normalize

Replace multiple slashes by one slash.

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 path

L_path_normalize_v

Shellcheck disable= SC2064

L_path_relative_to

Compute a version of the original path relative to the path represented by other path.

This method is string-based.

Option: -v <var> Store the output in variable instead of printing it.

Arguments:

  • $1 original path
  • $2 other path

See:

L_path_relative_to_v

Shellcheck disable= SC2179

L_path_is_relative_to

Check if a path is relative to other path.

This method is string-based; it neither accesses the filesystem nor treats “..” segments specially. Consider as alternative: L_path_relative_to -v tmp "$1" "$2" && [[ "$tmp" == ../* ]]

Example

   L_path_is_relative_to /etc/passwd /etc  # return 0
   L_path_is_relative_to /etc/passwd /usr  # return 1

Arguments:

  • $1 Path to check
  • $2 Path that $1 should be relative to.

L_path_append

Append a path to path variable if not already there.

Example

L_path_append PATH ~/.local/bin

Arguments:

  • $1 Variable name. For example PATH
  • $2 Path to append. For example /usr/bin
  • [$3] Optional path separator. Default: ':'

L_path_prepend

Prepend a path to path variable if not already there.

Example

L_path_append PATH ~/.local/bin

Arguments:

  • $1 Variable name. For example PATH
  • $2 Path to prepend. For example /usr/bin
  • [$3] Optional path separator. Default: ':'

L_path_remove

Remove a path from a path variable.

Example

L_path_append PATH ~/.local/bin

Arguments:

  • $1 Variable name. For example PATH
  • $2 Path to prepend. For example /usr/bin
  • [$3] Optional path separator. Default: ':'

L_dir_is_empty

Return 0 if a directory is empty.

Argument: $1 Directory.

string

Collection of functions to manipulate strings.

L_is_true

Return 0 if the string happend to be something like true.

Return 0 when argument is case-insensitive: - true - 1 - yes - y - t - any number except 0 - the character '+'

Argument: $1 str

L_is_false

Return 0 if the string happend to be something like false.

Return 0 when argument is case-insensitive: - false - 0 - no - F - n - the character minus '-'

Argument: $1 str

L_is_true_locale

Return 0 if the string happend to be something like true in locale.

Argument: $1 str

L_is_false_locale

Return 0 if the string happend to be something like false in locale.

Argument: $1 str

L_isprint

Return 0 if all characters in string are printable

Argument: $1 string to check

L_isdigit

Return 0 if all string characters are digits

Argument: $1 string to check

L_is_valid_variable_name

Return 0 if argument could be a variable name.

This function is used to make sure that eval "$1=" will e correct if L_is_valid_variable_name "$1".

Argument: $1 string to check

See: L_is_valid_variable_or_array_element

L_is_valid_variable_or_array_element

Return 0 if argument could be a variable name or array element.

Example

L_is_valid_variable_or_array_element aa           # true
L_is_valid_variable_or_array_element 'arr[elem]'  # true
L_is_valid_variable_or_array_element 'arr[elem'   # false

Argument: $1 string to check

See: L_is_valid_variable_name

L_is_valid_function_name

Is the string a valid Bash opinionated function name?

Almost anything is valid Bash function name.

Argument: $1 string to check

See:

L_is_integer

Return 0 if the string characters is an integer

Argument: $1 string to check

L_is_float

Return 0 if the string characters is a float

Argument: $1 string to check

$L_NL

newline

$L_TAB

tab

$L_SOH

Start of heading

$L_STX

Start of text

$L_EOT

End of Text

$L_EOF

End of transmission

$L_ENQ

Enquiry

$L_ACK

Acknowledge

$L_BEL

Bell

$L_BS

Backspace

$L_HT

Horizontal Tab

$L_LF

Line Feed

$L_VT

Vertical Tab

$L_FF

Form Feed

$L_CR

Carriage Return

$L_SO

Shift Out

$L_SI

Shift In

$L_DLE

Data Link Escape

$L_DC1

Device Control 1

$L_DC2

Device Control 2

$L_DC3

Device Control 3

$L_DC4

Device Control 4

$L_NAK

Negative Acknowledge

$L_SYN

Synchronous Idle

$L_ETB

End of Transmission Block

$L_CAN

Cancel

$L_EM

End of Medium

$L_SUB

Substitute

$L_ESC

Escape

$L_FS

File Separator

$L_GS

Group Separator

$L_RS

Record Separator

$L_US

Unit Separator

$L_DEL

Delete

$L_LBRACE

Left brace character

$L_RBRACE

Right brace character

$L_UUID

Looks random.

See: L_uuid4

$L_ALLCHARS

255 bytes with all possible 255 values

$L_ASCII_LOWERCASE

All lowercase characters a-z

$L_ASCII_UPPERCASE

All uppercase characters A-Z

$L_GPL_LICENSE_NOTICE_3_OR_LATER

The GPL3 or later License notice.

See: https://www.gnu.org/licenses/gpl-howto.en.html#license-notices

$L_FREE_SOFTWARE_NOTICE

notice that the software is a free software.

L_quote_setx

Output a string with the same quotating style as does bash in set -x

Option: -v <var> Store the output in variable instead of printing it.

Argument: $@ arguments to quote

L_quote_setx_v

L_quote_printf

Output a string with the same quotating style as does bash with printf

For single argument, just use printf -v var "%q" "$var". Use this for more arguments, like printf -v var "%q " "$@" results in a trailing space.

Option: -v <var> Store the output in variable instead of printing it.

Argument: $@ arguments to quote

L_quote_printf_v

L_quote_bin_printf

Output a string with the same quotating style as does /bin/printf

Option: -v <var> Store the output in variable instead of printing it.

Argument: $@ arguments to quote

L_quote_bin_printf_v

L_strhash

Convert a string to a number.

Option: -v <var> Store the output in variable instead of printing it.

L_strhash_v

L_strhash_bash

Convert a string to a number in pure bash.

Option: -v <var> Store the output in variable instead of printing it.

L_strhash_bash_v

L_strstr

Check if string contains substring.

Arguments:

  • $1 string
  • $2 substring

L_strupper

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 String to operate on.

L_strlower

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 String to operate on.

L_capitalize

Capitalize first character of a string.

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 String to operate on

L_uncapitalize

Lowercase first character of a string.

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 String to operate on

L_strip

Remove characters from IFS from begining and end of string

Option: -v <var> Store the output in variable instead of printing it.

Arguments:

  • $1 String to operate on.
  • [$2] Optional glob to strip, default is [:space:]

L_strip_v

Shellcheck disable= SC2295

L_lstrip

Remove characters from IFS from begining of string

Option: -v <var> Store the output in variable instead of printing it.

Arguments:

  • $1 String to operate on.
  • [$2] Optional glob to strip, default is [:space:]

L_lstrip_v

Shellcheck disable= SC2295

L_rstrip

Remove characters from IFS from begining of string

Option: -v <var> Store the output in variable instead of printing it.

Arguments:

  • $1 String to operate on.
  • [$2] Optional glob to strip, default is [:space:]

L_rstrip_v

Shellcheck disable= SC2295

L_list_functions_with_prefix

list functions with prefix

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 prefix

L_list_functions_with_prefix_v

L_list_functions_with_prefix_removed

list functions with prefix and remove the prefix

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 prefix

See: L_list_functions_with_prefix

L_list_functions_with_prefix_removed_v

L_abbreviation

Choose elements matching prefix.

Option: -v <var> Store the output in variable instead of printing it.

Arguments:

  • $1 prefix
  • $@ elements

L_abbreviation_v

L_float_cmp

compare two float numbers

The '<=>' operator returns 9 when $1 < $2, 10 when $1 == $2 and 11 when $1 > $2.

Example

   L_float_cmp 123.234 -le 234.345
   echo $?  # outputs 0
   L_exit_to ret L_float_cmp 123.234 -le 234.345
   echo "$ret"  # outputs 0

Arguments:

  • $1 one number
  • $2 operator, one of -lt -le -eq -ne -gt -ge > >= == != <= < <=>
  • $3 second number

L_float

A simple wrapper script around awk to evaluate float expressions.

Argument: $1 Expression to evaluate.

L_percent_format

Print a string with percent format.

Simple implementation of percent formatting in bash using regex and printf.

Example

  name=John
  declare -A age=([John]=42)
  L_percent_format "Hello, %(name)s! You are %(age[John])10s years old.\n"

Options:

  • -v <var> Store the output in variable instead of printing it.
  • -h Print this help and return 0.

Arguments:

  • $1 format string
  • $@ arguments

L_percent_format_v

Shellcheck disable= SC2059

L_fstring

print a string with f-string format

A simple implementation of f-strings in bash using regex and printf.

Example

 name=John
 declare -A age=([John]=42)
 L_fstring 'Hello, {name}! You are {age[John]:10s} years old.\n'

Options:

  • -v <var> Store the output in variable instead of printing it.
  • -h Print this help and return 0.

Argument: $1 format string

L_fstring_v

Shellcheck disable= SC2059

L_hexdump

Convert a string to hex dump.

Options:

  • -v <var> Store the output in variable instead of printing it.
  • -h Print this help and return 0.

L_hexdump_v

L_urlencode

Encode a string in percent encoding.

Options:

  • -v <var> Store the output in variable instead of printing it.
  • -h Print this help and return 0.

L_urlencode_v

L_urldecode

Decode percent encoding.

Options:

  • -v <var> Store the output in variable instead of printing it.
  • -h Print this help and return 0.

L_urldecode_v

L_html_escape

Escape characters for html.

Options:

  • -v <var> Store the output in variable instead of printing it.
  • -h Print this help and return 0.

L_html_escape_v

L_string_replace

Replace multiple characters in a string in order.

Note

I think this should be removed.

Example

L_string_replace -v string "$string" "&" "&amp;" "<" "&lt;"

Options:

  • -v <var> Store the output in variable instead of printing it.
  • -h Print this help and return 0.

Arguments:

  • $1 String to operate on.
  • $2 String to replace.
  • $3 Replacement.
  • $@ String to replace and replacement can be repeated multiple times.

See: L_html_escape

L_string_replace_v

L_string_count

Count the character in string.

Options:

  • -v <var> Store the output in variable instead of printing it.
  • -h Print this help and return 0.

Arguments:

  • $1 String.
  • $2 Character to count in string.

L_string_count_v

L_string_count_lines

Count lines in a string.

Options:

  • -v <var> Store the output in variable instead of printing it.
  • -h Print this help and return 0.

Argument: $1 String.

L_string_count_lines_v

L_string_split

Split a string with quotes without the risk of execution anything.

Rules: - https://www.gnu.org/software/bash/manual/html_node/Escape-Character.html - https://www.gnu.org/software/bash/manual/html_node/Single-Quotes.html - https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html - https://www.gnu.org/software/bash/manual/html_node/ANSI_002dC-Quoting.html

Why not xargs? To support ANSI-C quoting style $'' and support newlines in quotes.

Why not declare? Declare allows execution, declare -a array='($(echo something >&2))'executes echo.

Example

  $ L_string_split -v cmd "ls -l 'somefile; rm -rf ~'"
  $ declare -p cmd
  declare -a cmd=([0]="ls" [1]="-l" [2]="somefile; rm -rf ~")

Options:

  • -v <var> Store the output in variable instead of printing it.
  • -c Enable comments.
  • -A Disable ANSI-C quoting.
  • -h Print this help and return 0.

Shellcheck disable= SC1003

json

L_json_escape

Produces a string properly quoted for JSON inclusion

Poor man's jq

Example

   L_json_escape -v tmp "some string"
   echo "{\"key\":$tmp}" | jq .

Option: -v <var> Store the output in variable instead of printing it.

See:

L_json_escape_v

L_json_create

Very simple function to create JSON.

Every second argument is quoted for JSON, unless This argument is preceeded by a previous argument ending with ] or }, when the counter starts over.

Example

  L_json_make { \
    a : b , \
    b :[ 1 , 2 , 3 , 4 ] \
    c :[true, 1 ,null,false] \
  }
  #   ^^^^^^    ^^^^^^^^^^^^ - unquoted, added literally to the string
  # outputs: {"a":"b","b":[1,2,3,4],"c":[true,"1",false,null]}

array

Operations on various lists, arrays and arguments. L_array_*

L_array_len

Get array length.

Example

L_array_len arr

Options:

  • -v <var> Store the output in variable instead of printing it.
  • -h Print this help and return 0.

Argument: $1 <var array nameref

L_array_len_v

L_array_assign

Set elements of array.

Example

L_array_assign arr 1 2 3

Arguments:

  • $1 array nameref
  • $@ elements to set

L_array_set

Assign element of an array

Example

L_array_assign arr 5 "Hello"

Arguments:

  • $1 array nameref
  • $2 array index
  • $3 value to assign

L_array_append

Append elements to array.

Example

L_array_append arr "Hello" "World"

Arguments:

  • $1 array nameref
  • $@ elements to append

L_array_insert

Insert element at specific position in an array.

This will move all elements from the position to the end of the array.

Example

L_array_insert arr 2 "Hello" "World"

Arguments:

  • $1 array nameref
  • $2 index position
  • $@ elements to append

L_array_pop_front

Remove first array element.

Argument: $1 array nameref

L_array_pop_back

Remove last array element.

Example

L_array_pop_back arr

Argument: $1 array nameref

L_array_is_dense

Return success, if all array elements are in sequence from 0.

Example

if L_array_is_dense arr; then echo "Array is dense"; fi

Argument: $1 array nameref

L_array_prepend

Append elements to the front of the array.

Example

L_array_prepend arr "Hello" "World"

Arguments:

  • $1 array nameref
  • $@ elements to append

L_array_clear

Clear an array.

Example

L_array_clear arr

Argument: $1 array nameref

L_array_extract

Assign array elements to variables in order.

Example

  arr=("Hello" "World")
  L_array_extract arr var1 var2
  echo "$var1"  # prints Hello
  echo "$var2"  # prints World

Arguments:

  • $1 array nameref
  • $@ variables to assign to

L_array_reverse

Reverse elements in an array.

Example

    arr=("world" "Hello")
    L_array_reverse arr
    echo "${arr[@]}"  # prints Hello world

Argument: $1 array nameref

L_readarray

Wrapper for readarray for bash versions that do not have it.

Example

L_readarray arr <file

Options:

  • -d <delim> separator to use, default: newline
  • -u <fd> file descriptor to read from
  • -s <count> skip first n lines
  • -h Print this help and return 0.

Argument: $1 array nameref

L_array_pipe

Pipe an array to a command and then read back into an array.

Example

  arr=("Hello" "World")
  L_array_pipe arr tr '[:upper:]' '[:lower:]'
  echo "${arr[@]}"  # prints hello world

Option: -z Use null byte as separator instead of newline.

Arguments:

  • $1 array nameref
  • $@ command to pipe to

Shellcheck disable= SC2059

L_array_contains

check if array variable contains value

Example

  arr=("Hello" "World")
  L_array_contains arr "Hello"
  echo $?  # prints 0

Arguments:

  • $1 array nameref
  • $2 needle

L_array_filter_eval

Remove elements from array for which expression evaluates to failure.

Example

 arr=("Hello" "World")
 L_array_filter_eval arr '[[ "$1" == "Hello" ]]'
 echo "${arr[@]}"  # prints Hello

Arguments:

  • $1 array nameref
  • $2 expression to evaluate with array element of index L_i and value $1

L_array_index

Find an index of an element in the array equal to second argument.

Option: -v <var> Store the output in variable instead of printing it.

Arguments:

  • $1 array nameref
  • $2 element to find

L_array_index_v

L_array_join

Join array elements separated with the second argument.

Example

  arr=("Hello" "World")
  L_array_join -v res arr ", "
  echo "$res"  # prints Hello, World

Options:

  • -v <var> Store the output in variable instead of printing it.
  • -h Print this help and return 0.

Arguments:

  • $1 array nameref
  • $2 string to join elements with

See: L_args_join

L_array_join_v

L_array_andjoin

Options:

  • -v <var> Store the output in variable instead of printing it.
  • -h Print this help and return 0.

Argument: $1 array nameref

See: L_args_andjoin

L_array_andjoin_v

args

Operations on list of arguments.

L_args_join

Join arguments with separator

Example

  L_args_join -v res ", " "Hello" "World"
  echo "$res"  # prints Hello, World

Option: -v <var> Store the output in variable instead of printing it.

Arguments:

  • $1 separator
  • $@ arguments to join

See: L_array_join

L_args_join_v

L_args_andjoin

Join arguments with ", " and last with " and "

Option: -v <var> Store the output in variable instead of printing it.

Argument: $@ arguments to join

L_args_andjoin_v

L_args_contain

Check if arguments starting from second contain the first argument.

Example

  L_args_contain "Hello" "Hello" "World"
  echo $?  # prints 0

Arguments:

  • $1 needle
  • $@ heystack

L_args_index

Get index number of argument equal to the first argument.

Example

  L_args_index -v res "World" "Hello" "World"
  echo "$res"  # prints 1

Option: -v <var>

Arguments:

  • $1 needle
  • $@ heystack

L_args_index_v

L_max

return max of arguments

Example

L_max -v max 1 2 3 4

Option: -v <var> Store the output in variable instead of printing it.

Argument: $@ int arguments

L_max_v

Sets variable: L_v

Shellcheck disable= SC1105 SC2094 SC2035

L_min

return max of arguments

Example

L_min -v min 1 2 3 4

Option: -v <var> Store the output in variable instead of printing it.

Argument: $@ int arguments

L_min_v

Sets variable: L_v

Shellcheck disable= SC1105 SC2094 SC2035

utilities

Various self contained functions that could be separate programs.

L_table

Make a table

Example

    $ L_table -R1-2 "name1 name2 name3" "a b c" "d e f"
    name1 name2 name3
        a     b c
        d     e f

Options:

  • -v <var> Store the output in variable instead of printing it.
  • -s <separator> IFS column separator to use. Default: space or tab.
  • -o <str> Output separator to use
  • -R <list[int]> Right align columns with these indexes
  • -h Print this help and return 0.

Argument: $@ Lines to print, joined and separated by newline.

Shellcheck disable= SC1105 SC2201 SC2102 SC2035 SC2211 SC2283 SC2094

L_parse_range_list

Parse cut range list into an array.

Each LIST is made up of one range, or many ranges separated by commas. Selected input is written in the same order that it is read, and is written exactly once. Each range is one of: N N'th byte, character or field, counted from 1 N- from N'th byte, character or field, to end of line N-M from N'th to M'th (included) byte, character or field -M from first to M'th (included) byte, character or field

Example

    $ L_parse_range_list 100 1-4,3-5
    1
    2
    3
    4
    5
    $ L_parse_range_list -v tmp 100 '1-4 3-5'
    $ echo "${tmp[@]}"
    1 2 3 4 5
    $ if L_args_contain 3 "${tmp[@]}"; then echo "yes"; else echo "no"; fi
    yes
    $ if L_args_contain 7 "${tmp[@]}"; then echo "yes"; else echo "no"; fi
    no

Option: -v <var> Store the output in variable instead of printing it.

Arguments:

  • $1 max number of fields
  • $2 list of fields

L_parse_range_list_v

L_pretty_print

Prints values with declare, but array values are on separate lines.

Options:

  • -p <str> Prefix each line with this prefix
  • -v <var> Store the output in variable instead of printing it.
  • -w <int> Set terminal width. This modifies compact output line wrapping.
  • -n Enable pretty printing nested arrays
  • -C Disable compact output for arrays, i.e. each key is on separate line.
  • -h Print this help and return 0.

Argument: $@ variable names to pretty print

L_argskeywords

Parse python-like positional and keyword arguments format.

The difference to python is that @ is used instead of *, becuase * triggers filename expansion. An argument -- signifies end of arguments definition and start of arguments to parse.

Example

  range() {
     local start stop step
      L_argskeywords start stop step=1 -- "$@" || return 2
      for ((; start < stop; start += stop)); do echo "$start"; done
  }
  range start=1 stop=6 step=2
  range 1 6

  max() {
     local arg1 arg2 args key
     L_argskeywords arg1 arg2 @args key='' -- "$@" || return 2
     ...
  }
  max 1 2 3 4

  int() {
     local string base
     L_argskeywords string / base=10 -- "$@" || return 2
     ...
  }
  int 10 7 # error
  int 10 base=7

Options:

  • -A <var> Instead of storing in variables, store values in specified associative array with variables as key.
  • -M Use L_map instead of associative array, for @@kwargs and -A option. Usefull for older Bash.
  • -E Exit on error
  • -e <str> Prefix error messages with this prefix. Default: "${FUNCNAME[1]}:L_argskeywords:"
  • -h Print this help and return 0.

Arguments:

  • $@ Python arguments format specification
  • $2 --
  • $@ Arguments to parse

See:

L_version_cmp

Compare version numbers.

Arguments:

  • $1 str one version
  • $2 str one of: -lt -le -eq -ne -gt -ge '<' '<=' '==' '!=' '>' '>=' '~='
  • $3 str second version
  • [$4] int accuracy, how many at max elements to compare? By default up to 3.

Shellcheck disable= SC2053

See: https://peps.python.org/pep-0440/

log

logging library

This library is meant to be similar to python logging library.

was log system configured?

_L_logconf_configured=0

int current global log level

_L_logconf_level=$L_LOGLEVEL_INFO

1 or 0 or ''. Should we use the color for logging output?

_L_logconf_color=

if this regex is set, allow elements

_L_logconf_selecteval=

default formatting function

_L_logconf_formateval='L_log_format_default "$@"'

default outputting function

_L_logconf_outputeval=L_log_output_to_stderr

Example

    L_log_set_level ERROR
    L_error "this is an error"
    L_info "this is information"
    L_debug "This is debug"

$L_LOGLEVEL_CRITICAL

$L_LOGLEVEL_ERROR

$L_LOGLEVEL_WARNING

$L_LOGLEVEL_NOTICE

$L_LOGLEVEL_INFO

$L_LOGLEVEL_DEBUG

$L_LOGLEVEL_TRACE

$L_LOGLEVEL_NAMES

convert log level to log name

$L_LOGLEVEL_COLORS

get color associated with particular loglevel

Shellcheck disable= SC2153

L_log_configure

Configure L_log module.

Example

  L_log_configure \
    -l debug \
    -c 0 \
    -f 'printf -v L_logline "${@:2}"' \
    -o 'printf "%s\n" "$L_logline" >&2' \
    -s '[[ $L_logline_source == */script.sh ]]'

Options:

  • -h Print this help and return 0.
  • -r Allow for reconfiguring L_log system. Otherwise the next call of this function is ignored.
  • -l <LOGLEVEL> Set loglevel. Can be \$L_LOGLEVEL_INFO INFO or 30. Default: $_L_logconf_level
  • -c <BOOL>

    Set to 1 to enable the use of color, set to 0 to disable the use of color.

                         Set to '' empty string to detect if stdout has color support. Default: ''
    
  • -f <FORMATEVAL>

    Evaluate expression for formatting. Default: 'L_log_format_default "$@"'

                         The function should format arguments and put the message into the L_logline variable.
    
  • -F <FORMATFUNC> Equal to -f ' "$@"'. Shorthand to use a function.
  • -s <SELECTEVAL> If eval "SELECTEVAL" exits with nonzero, do not print the line. Default: ''
  • -o <OUTPUTEVAL>

    Evaluate expression for outputting. Default: L_log_output_to_stderr

                         The function should output the content of L_logline.
    
  • -L Equal to -F L_log_format_long
  • -J Equal to -F L_log_format_json

Arguments: Takes no arguments

L_log_level_inc

increase log level

Argument: $1 amount, default: 10

L_log_level_dec

decrease log level

Argument: $1 amount, default: 10

L_log_level_to_int_to

Convert log string to number

Arguments:

  • $1 str variable name
  • $2 int|str loglevel like INFO info or 30

L_log_is_enabled_for

Check if log of such level is enabled to log.

Argument: $1 str|int loglevel or log string

L_log_format_default

Default logging formatting

Arguments:

  • $1 str log line printf format string
  • $@ any log line printf arguments

L_log_format_long

Format logline with timestamp information.

Arguments:

  • $1 str log line printf format string
  • $@ any log line printf arguments

L_log_format_json

Output logs in json format.

Shellcheck disable= SC2059

L_log_output_to_stderr

Output L_logline to stderr.

L_log_output_to_logger

Output L_logline with logger.

Argument: $@ message to output

L_log

main logging entrypoint

Options:

  • -s <int> Increment stacklevel by this much
  • -l <int|string> loglevel to print log line as

Argument: $@ any log arguments

Shellcheck disable= SC2140

Return: 0 if nothing was logged, or the exit status of formatter && outputter functions.

L_critical

output a critical message

Option: -s <int> stacklevel increase

Argument: $1 message

L_error

output a error message

Option: -s <int> stacklevel increase

Argument: $1 message

L_warning

output a warning message

Option: -s <int> stacklevel increase

Argument: $1 message

L_notice

output a notice

Option: -s <int> stacklevel increase

Argument: $1 message

L_info

output a information message

Option: -s <int> stacklevel increase

Argument: $1 message

L_debug

output a debugging message

Option: -s <int> stacklevel increase

Argument: $1 message

L_trace

output a tracing message

Option: -s <int> stacklevel increase

Argument: $1 message

L_fatal

Output a critical message and exit the script with 2.

Argument: $@ L_critical arguments

L_logrun

log a command and then execute it

Is not affected by L_dryrun variable.

Argument: $@ command to execute

$L_dryrun

set to 1 if L_run should not execute the function.

L_run

Logs the quoted argument with a leading +.

if L_dryrun is nonzero, executes the arguments.

Options:

  • -l <loglevel> Set loglevel.
  • -s <stacklevel> Increment stacklevel by this number.
  • -h Print this help and return 0.

Argument: $@ command to execute

Uses environment variable: L_dryrun

sort

Array sorting function.

L_shuf_bash

Shuffle an array

Argument: $1 array nameref

L_shuf_cmd

Shuffle an array using shuf command

Option: -z --zero-terminated use zero separated stream with shuf -z

Arguments:

  • $* any options are forwarded to shuf command
  • $-1 array nameref

L_shuf

Shuffle an array

Argument: $1 array nameref

L_sort_bash

Quicksort an array in place in pure bash.

Options:

  • -z ignored. Always zero sorting
  • -n numeric sort, otherwise lexical
  • -r reverse sort
  • -c <compare> custom compare function that returns 0 when $1 > $2 and 1 otherwise
  • -h Print this help and return 0.

Argument: $1 array nameref

See: L_sort

L_sort_cmd

Sort an array using sort command.

Even in most optimized code that I could write for bash sorting, still executing sort command is faster. The difference becomes significant for large arrays. Sorting 100 element array with bash is 0.049s and with sort is 0.022s.

Example

   arr=(5 2 5 1)
   L_sort_cmd -n arr
   echo "${arr[@]}"  # 1 2 5 5

Options:

  • -z --zero-terminated use zero separated stream with sort -z
  • -n numeric sort

Arguments:

  • $* any options are forwarded to sort command
  • $-1 last argument is the array nameref

L_sort

Sort a bash array.

If sort command exists, use L_sort_cmd, otherwise use L_sort_bash. If you have a custom sorter, use L_sort_bash, otherwise prefer L_sort_cmd for speed.

Options:

  • -z Use zero separated stream with sort -z
  • -n numeric sort
  • -r reverse sort

Argument: $1 array nameref

See:

trap

L_print_traceback

Prints traceback

:

  Example traceback:
  Traceback from pid 3973390 (most recent call last):
    File ./bin/L_lib.sh, line 2921, in main()
  2921 >> _L_lib_main "$@"
    File ./bin/L_lib.sh, line 2912, in _L_lib_main()
  2912 >>                 "test") _L_lib_run_tests "$@"; ;;
    File ./bin/L_lib.sh, line 2793, in _L_lib_run_tests()
  2793 >>                 "$_L_test"
    File ./bin/L_lib.sh, line 891, in _L_test_other()
  891  >>                 L_unittest_eq "$max" 4
    File ./bin/L_lib.sh, line 1412, in L_unittest_eq()
  1412 >>                 _L_unittest_showdiff "$1" "$2"
    File ./bin/L_lib.sh, line 1391, in _L_unittest_showdiff()
  1391 >>                 sdiff <(cat <<<"$1") - <<<"$2"

Arguments:

  • [$1] int stack offset to start from (default: 0)
  • [$2] int number of lines to show around the line (default: 2)

L_print_caller

Print simple traceback using builtin caller command.

L_trap_err_small

Callback to be exectued on ERR trap that prints just the caller.

Example

  trap 'L_trap_err_small' ERR

L_trap_err

description Callback to be exectued on ERR trap that prints a traceback and exits.

Example

   trap 'L_trap_err $?' ERR
   trap 'L_trap_err $?' EXIT

Argument: $1 int exit code

L_trap_err_enable

Enable ERR trap with L_trap_err as callback

set -eEo functrace and register trap 'L_trap_err $?' ERR.

Example

 L_trap_err_enable

L_trap_err_disable

Disable ERR trap

Example

  L_trap_err_disable

L_trap_err_init

If set -e is set and ERR trap is not set, enable ERR trap with L_trap_err as callback

Example

   L_trap_err_init

L_trap_names

Return an array of all trap names. Index is the trap name number.

Option: -v <var>

L_trap_names_v

L_trap_to_number

Convert trap name to number.

The DEBUG ERROR and RETURN traps have a number as reported by $BASH_TRAPSIG inside the handler, but the number can't be used to register the trap with trap command.

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 trap name or trap number

L_trap_to_number_v

L_trap_to_name

convert trap number to trap name

Example

L_trap_to_name -v var 0 && L_assert '' test "$var" = EXIT

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 signal name or signal number

L_trap_to_name_v

L_trap_get

Get the current value of trap

Example

  trap 'echo hi' EXIT
  L_trap_get -v var EXIT
  L_assert '' test "$var" = 'echo hi'

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 signal name or number

L_trap_get_v

L_trap_push

Add a newline and the command to the trap value.

Arguments:

  • $1 str command to execute
  • $2 str signal to handle

Shellcheck disable= SC2064

See: L_trap_pop

L_trap_pop

Remove a line from the trap value from the end up until the last newline.

Argument: $1 str signal to handle

Shellcheck disable= SC2064

See: L_trap_push

L_trap

Trap function with reversed order of arguments, to force expansions upon calling.

Arguments:

  • $1 Space or comma separated list of signal names or numbers.
  • $@ Action to execute.

finally

Properly preserve exit status for parent processes. https://www.cons.org/cracauer/sigint.html Re-signaling does not work properly on specific signals. Re-signaling does not work properly in subshells and subshell exits with 0.

Array of commands to execute on EXIT.

_L_finally_arr=()

Array of commands to execute on function returns.

When a function returns at stack depth given by ${#BASH_LINENO[@]} the _L_finally_return[${#BASH_LINENO[@]}] should be executed. _L_finally_return=()

BASHPID that registered traps.

_L_finally_pid=""

Holds signal received inside a critical section.

[0] - signal name [1] - signal number _L_finally_pending=()

Currently handled signal name.

Special values: RETURN EXIT POP NONE POP - when calling from L_finally_pop NONE - used inside critical section. L_SIGNAL=""

Currently handled signal number.

Unset when handling RETURN or POP. 0 for EXIT trap. L_SIGNUM=""

The value of $? as expanded by trap.

L_SIGRET=""

L_finally_handle_return

L_finally RETURN handler.

Arguments:

  • $1 The value of $?.
  • $2 The value of $BASH_COMMAND.

L_finally_handle_exit

L_finally EXIT handler.

L_finally_handle_signal

L_finally signal handler.

Arguments:

  • $1 The trap signal name to handle.
  • $2 The trap signal number to handle.

L_finally_list

List elements registered by L_finally.

L_finally

Register an action to be executed upon termination.

The action will be executed only exactly once, even if the signal is received multiple times. The signal exit code of the program or subshell is preserved. The variable $L_SIGNAL is set to the currently handled signal name and available in action.

Warning

The function assumes full ownership of all trap values.

This is needed to properly set traps accross PIDs and subshells and functions and on Bash below 5.2. Bash below 5.2 does not execute EXIT trap in subshells after receiving a signal, so L_finally trap handler is registered on all possible signals. The signal exit status is preserved.

Example

   tmpf=$(mktemp)
   L_finally rm "$tmpf"

   calculate_something() {
      local tmpf
      tmpf=$(mktemp)
      L_finally -r rm "$tmpf"
      echo use tmpf >"$tmpf"
      # tmpf automatically cleaned up once on RETURN or EXIT or signal, whichever comes first.
   }

Options:

  • -r

    Set trace attribute on the function and add RETURN trap to register the function on.

           This does not work correctly with source and instead source RETURN trap will execute parent scope actions.
           To mitigate this, wrap source in a function, for example use L_source.
    
  • -s <int>

    Increment the stack offset for the RETURN trap by this number.

           The RETURN trap handler will execute the action only if called from
           the nth position in the stack relative to the current position. Default: 0
    
  • -l

    Add action to be executed last, not first of the stack.

           Calling L_finally_pop after registering such action is undefined.
    
  • -R Force reregister all the traps. Unless this option, traps are only registered on the first call of a BASHPID.
  • -v <var>

    Store the action index in the variable.

           This index can be used with `L_finally_pop -i` to remove the action.
    
  • -h Print this help and return 0.

Argument: $@

Action to execute. When action is missing, then only traps are registered.

The command may not call eval 'return'. It would just return from the handler function.

Shellcheck disable= SC2089 SC2090

See: L_finally_pop

L_finally_pop

Execute and unregister the last action registered with L_finally.

Options:

  • -n Do not execute the action, only remove.
  • -i <index> Remove action of index .
  • -h Print this help and return 0.

Return:

1 if nothing was popped, 2 on invalid usage,

otherwise return the exit status of the executed action.

See: L_finally

L_finally_critical_section

Execute a command inside a critical section.

The signals will be raised after the command is finished. Prerequisite: L_finally has registered signal handlers.

Argument: $@ Command to execute.

with

What we can do with finally? We can do destructors.

L_with_cd

Change to given directory.

Register RETURN trap for parent function that will restore current working directory.

Arguments:

  • $1 Directory to cd into.
  • $2 Optional stack offset to add to RETURN trap.

L_with_tmpfile_to

Create a temporary directory.

Register RETURN trap for parent fuction that will remove the directory.

Arguments:

  • $1 Variable to assign the temporary file to.
  • $2 Optional stack offset to add to RETURN trap.

L_with_tmpdir_to

Create a temporary directory.

Register RETURN trap for parent fuction that will remove the directory.

Arguments:

  • $1 Variable to assign the temporary directory location to.
  • $2 Optional stack offset to add to RETURN trap.

L_with_cd_tmpdir

Create a temporary directory and cd into it.

Register RETURN trap that will remove the temporary directory and restore working directory on return from parent function.

Argument: $2 Optional stack offset to add to RETURN trap.

L_with_redirect_stdout_to

Temporary redirect stdout to string.

Non-forking command substition for the poor.

Arguments:

  • $1 Variable to capture stdout to.
  • $2 Optional stack offset to add to RETURN trap.

unittest

Testing library

Simple unittesting library that does simple comparison. Testing library for testing if variables are commands are returning as expected.

Note

rather stable

Example

   L_unittest_eq 1 1

$L_unittest_fails

Integer that increases with every failed test.

$L_unittest_exit_on_error

Set this variable to 1 to exit immediately when a test fails.

$L_unittest_unset_x

Set this varaible to 1 to disable set -x inside L_unittest functions, Set to 0 to don't.

L_unittest_main

Get all functions that start with a prefix specified with -P and execute them one by one.

Options:

  • -h help
  • -P <prefix> Get functions with this prefix to test
  • -r <regex> filter tests with regex
  • -E exit on error

L_unittest_checkexit

Check if command exits with specified exitcode.

Arguments:

  • $1 exit code the command should exit with
  • $@ command to execute

Shellcheck disable= SC2035

L_unittest_success

Check if command exits with 0

Argument: $@ command to execute

L_unittest_failure

Check if command exits with non zero

Argument: $@ command to execute

L_unittest_failure_capture

capture stdout and stderr into variables of a failed command

Arguments:

  • $1 var stdout and stderr output
  • $@ command to execute

L_unittest_cmd

Test execution of a command and capture and test it's stdout and/or stderr output.

Local variables used by this function start with _L_u. Options with L_uopt. This function optionally runs the command in the current shell or not depending on options.

Example

  echo Hello world /tmp/1
  L_unittest_cmd -r 'world' grep world /tmp/1
  L_unittest_cmd -r 'No such file or directory' ! grep something not_existing_file

Options:

  • -h Print this help and return 0.
  • -c Run in current execution environment, instead of using a subshell.
  • -i Invert exit status. You can also use ! or L_not in front of the command.
  • -I Do not close stdin <&1 . By default it is closed.
  • -f Expect the command to fail. Equal to -i -j -N.
  • -N Redirect stdout of the command to >/dev/null.
  • -j Redirect stderr to stdout of the command. 2>&1
  • -x Run the command inside set -x
  • -X Do not modify set -x
  • -v <var> Store the output in variable instead of printing it.
  • -r <regex> Compare output of the command with this regex.
  • -o <str> Compare output of the command with this string.
  • -e <int> Command should exit with this exit status (default: 0)
  • -s <int> Stack up

Argument: $@

Command to execute.

If a command starts with !, this implies -i and, if one of -v -r -o option is used, it implies -j.

L_unittest_vareq

Test if a variable has specific value.

Arguments:

  • $1 variable nameref
  • $2 value

L_unittest_eq

Test if two strings are equal.

Arguments:

  • $1 one string
  • $2 second string

L_unittest_arreq

Test if array is equal to elements.

Arguments:

  • $1 array variable
  • $@ values

L_unittest_ne

Test two strings are not equal.

Arguments:

  • $1 one string
  • $2 second string

L_unittest_regex

test if a string matches regex

Arguments:

  • $1 string
  • $2 regex

L_unittest_contains

Test if a string contains other string.

Arguments:

  • $1 string
  • $2 needle

map

Key value store without associative array support

L_map consist of an null initial value. L_map stores keys and values separated by a tab, with an empty leading newline. Value is qouted by printf %q . Map key may not contain newline or tab characters.

                # empty initial newline
key<TAB>$'value'
key2<TAB>$'value2' # no trailing newline

This format matches the regexes used in L_map_get for easy extraction using bash variable substitution. The map depends on printf %q never outputting a newline or a tab character, instead using $'\t\n' form.

L_map_assign

Initializes a map

Example

   local var
   L_map_assign var a 1 b 2

Arguments:

  • $1 var variable name holding the map
  • $@ Pairs of keys and values to assign to the map.

L_map_clear

Clear a map

Argument: $1 var variable name holding the map

L_map_remove

Clear a key of a map

Example

    L_map_assign var a 1
    L_map_remove var a
    if L_map_has var a; then
      echo "a is set"
    else
      echo "a is not set"
    fi

Arguments:

  • $1 var map
  • $2 str key

L_map_set

Set a key in a map to value

Example

  L_map_assign var
  L_map_set var a 1
  L_map_set var b 2

Arguments:

  • $1 var map
  • $2 str key
  • $3 str value

L_map_set_noremove

Set a key in a map to value, potentially resulting in duplicate keys.

Arguments:

  • $1 var map
  • $2 str key
  • $3 str value

L_map_get

Assigns the value of key in map.

If the key is not set, then assigns default if given and returns with 1. You want to prefer this version of L_map_get

Example

   L_map_clear var
   L_map_set var a 1
   L_map_get -v tmp var a
   echo "$tmp"  # outputs: 1

Option: -v <var> Store the output in variable instead of printing it.

Arguments:

  • $1 var map
  • $2 str key
  • [$3] str default

L_map_get_v

L_map_has

Example

    L_map_clear var
    L_map_set var a 1
    if L_map_has var a; then
      echo "a is set"
    fi

Arguments:

  • $1 var map
  • $2 str key

Exit: 0 if map contains key, nonzero otherwise

L_map_setdefault

set value of a map if not set

Arguments:

  • $1 var map
  • $2 str key
  • $3 str default value

L_map_append

Append value to an existing key in map

Arguments:

  • $1 var map
  • $2 str key
  • $3 str value to append

L_map_keys

List all keys in the map.

Example

  L_map_clear var
  L_map_set var a 1
  L_map_set var b 2
  L_map_keys -v tmp var
  echo "${tmp[@]}"  # outputs: 'a b'

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 var map

L_map_keys_v

L_map_values

List all values in the map.

Example

   L_map_clear var
   L_map_set var a 1
   L_map_set var b 2
   L_map_values -v tmp var
   echo "${tmp[@]}"  # outputs: '1 2'

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 var map

L_map_values_v

L_map_items

List items on newline separated key value pairs.

Example

  L_map_clear var
  L_map_set var a 1
  L_map_set var b 2
  L_map_items -v tmp var
  echo "${tmp[@]}"  # outputs: 'a 1 b 2'

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 var map

L_map_items_v

L_map_load

Load all keys to variables with the name of $prefix$key.

Example

    L_map_clear var
    L_map_set var a 1
    L_map_set var b 2
    L_map_load var PREFIX_
    echo "$PREFIX_a $PREFIX_b"  # outputs: 1 2

Arguments:

  • $1 map variable
  • $2 prefix
  • $@ Optional list of keys to load. If not set, all are loaded.

L_map_save

Save all variables with prefix to a map.

Example

   L_map_clear var
   PREFIX_a=1
   PREFIX_b=2
   L_map_save var PREFIX_
   L_map_items -v tmp var
   echo "${tmp[@]}"  # outputs: 'a 1 b 2'

Arguments:

  • $1 map variable
  • $2 prefix

asa

Collection of function to work on associative array.

Maybe will renamed to dict. "asa" sounds better than "assarray", less confusing than "asarray" and shorter that associative array.

Note

unstable

L_asa_copy

Copy associative dictionary.

Notice: the destination array is not cleared. Slowish, O(N). Iterates of keys one by one. Use L_asa_assign

Arguments:

  • $1 var Source associative array
  • $2 var Destination associative array
  • [$3] str Filter only keys with this regex

See: L_asa_assign

L_asa_has

check if associative array has key

Arguments:

  • $1 associative array nameref
  • $2 key

L_asa_is_empty

check if associative array is empty

Argument: $1 associative array nameref

L_asa_get

Get value from associative array

Option: -v <var> Store the output in variable instead of printing it.

Arguments:

  • $1 associative array nameref
  • $2 key
  • [$3] optional default value

Exit: 1 if no key found and no default value

L_asa_get_v

L_asa_len

get the length of associative array

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 associative array nameref

L_asa_len_v

L_asa_keys

get keys of an associative array

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 associative array nameref

L_asa_keys_v

L_asa_keys_sorted

get keys of an associative array in a sorted

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 associative array nameref

L_asa_keys_sorted_v

L_asa_set

assign value to associative array

You might think why this function exists? In case you have associative array name in a variable.

Example

   local -A map
   printf -v "map[a]" "%s" val  # will fail in bash 4.0
   L_asa_set map a val  # will work in bash4.0

Arguments:

  • $1 assoatiative array variable
  • $2 key to assign to
  • $3 value to assign

L_asa_assign

Copy associative dictionary

Notice: the destination array is cleared. Much faster then L_asa_copy. Note: Arguments are in different order.

Example

  local -A map=([a]=b [c]=d)
  local -A mapcopy=()
  L_asa_assign mapcopy = map

Arguments:

  • $1 var Destination associative array
  • $2 =
  • $3 var Source associative array

See:

L_asa_cmp

check if one associative array is equal to another

Example

   local -A a=([a]=1 [b]=2)
   local -A b=([a]=1 [b]=2)
   if L_asa_cmp a b; then
       echo "equal"
   fi

Arguments:

  • $1 associative array name
  • $2 associative array name

Exit: 0 if equal, 1 otherwise

argparse

argument parsing in bash

L_argparse_fatal

Print argument parsing error and exit.

Uses environment variables:

  • L_NAME
  • _L_parser

Exit: 1

L_argparse_print_help

Print help or only usage for given parser or global parser.

Syntax:

Usage: prog_name cmd1 cmd2 [-abcd] [+abcd] [--option1] [-o ARG] arg
                                                                ^^^  - _L_args_usage
                                           ^^^^^^^^^^^^^^^^^^^^      - _L_options_usage
                           ^^^^^^^ ^^^^^^                            - _L_options_usage_noargs
       ^^^^^^^^^^^^^^^^^^^                                           - _L_prog
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  - usage string
Options:
  -o --option ARG     Help message
                      ^^^^^^^^^^^^   - help message
  ^^^^^^^^^^^^^^^                    - name
  ^^^^^^^^^^^^^^^$'\n'^^^^^^^^^^^    - _L_usage_args_helps _L_usage_cmds_helps _L_options_helps

Option: -s --short print only usage, not full help

Shellcheck disable= SC2120

L_argparse_print_usage

Print usage.

Shellcheck disable= SC2120

$L_argparse_template_help

Add -h --help option

Example

L_argparse -- "${L_argparse_template_help[@]}" ---- "$@"

See: L_argparse_template_verbose

$L_argparse_template_verbose

Add -v --verbose option that increases log level

Example

L_argparse -- "${L_argparse_template_verbose[@]}" ---- "$@"

See: L_argparse_template_quiet

$L_argparse_template_quiet

Add -q --quiet options that decreses log level

Example

L_argparse -- "${L_argparse_template_quiet[@]}" ---- "$@"

See: L_argparse_template_dryrun

$L_argparse_template_dryrun

Add -n --dryrun argument to argparse.

Example

L_argparse -- "${_L_argparse_template_dryrun[@]}" ---- "$@"

See: L_argparse_template_help

L_argparse_validator

Validate arguments inside validator for argparse.

In case of validation error, prints the error message.

Arguments:

  • $1 error message
  • $2 value to validate
  • $@ command to execute for validation

Exit: 1 if validation fails

See: _L_argparse_validator_int

L_argparse_compgen

Run compgen that outputs correctly formatted completion stream.

With option description prefixed with the 'plain' prefix. Any compgen option is accepted, arguments are forwarded to compgen.

Options:

  • --ANY Any options supported by compgen, except -P and -S
  • -D <str> Specify the description of appended to the result. If description is an empty string, it is not printed. Default: help of the option.

Argument: $1 incomplete

Exit: 0 if compgen returned 0 or 1, otherwise 2

L_argparse

Parse command line aruments according to specification.

This command takes groups of command line arguments separated by -- with sentinel ---- . The first group of arguments are arguments _L_parser. The next group of arguments are arguments _L_optspec. The last group of arguments are command line arguments passed to _L_argparse_parse_args.

Note

the last separator ---- is different to make it more clear and restrict parsing better.

proc

Processes and jobs related functions.

L_bashpid_to

Get bashpid in a way compatible with Bash before 4.0.

Argument: $1 Variable to store the result to.

L_raise

Send signal to itself.

Argument: $@ Kill arguments. See kill --help.

L_kill_all_jobs

L_wait_all_jobs

L_get_all_childs

Get all pids of all child processes including grandchildren recursively.

Option: -v <var>

Argument: [$1] Pid of the parent. Default: $BASHPID.

See: https://stackoverflow.com/a/52544126/9072753

L_get_all_childs_v

L_kill_all_childs

Kills all childs of the pid.

Arguments:

  • -sigspec Signal to use.
  • [$1] Pid of the process to kill all childs of. Defualt: $BASHPID

L_is_fd_open

Check if file descriptor is open.

Argument: $1 file descriptor

Shellcheck disable= SC2188

L_get_free_fd_to

Get free file descriptors

Argument: $@ variables to assign with the file descriptor numbers

L_pipe

Open two connected file descriptors.

This internally creates a temporary file with mkfifo The result variable is assigned an array that: - [0] element is input from the pipe, - [1] element is the output to the pipe. This is meant to mimic the pipe() C function.

Arguments:

  • <var> variable name to assign result to
  • [str] template temporary filename, default: ${TMPDIR:/tmp}/L_pipe_XXXXXXXXXX

L_proc_popen

Process open. Coproc replacement.

The input/output options are in three groups:

  • -I and -i for stdin,
  • -O and -o for stdout,
  • -E and -e for stderr.

Uppercase letter option specifies the mode for the file descriptor.

There are following modes available that you can give to uppercase options -I -O and -E:

  • null - redirect to or from /dev/null
  • close - close the file descriptor >&-
  • input - -i specifies the string to forward to stdin. Only allowed for -I.
  • stdout - connect file descriptor to stdout. -o or -e value are ignored.
  • stderr - connect file descriptor to stderr. -o or -e value are ignored.
  • pipe - create a fifo and connect file descriptor to it. -i -o or -e option specifies part of the temporary filename.
  • file - connect file descriptor to file specified by -i -o or -e option
  • fd - connect file descriptor to another file descriptor specified by -i -o or -e option

There first argument specifies an output variable that will be assigned string with content: <exitcode> pid<pid> 0fd<stdin> 1fd<stdout> 2fd<stderr>\t<cmd...>.

The outputs variable contains elements:

  • <exitcode> - Exitcode or empty if not yet finished.
  • <pid> - Pid.
  • <stdin> - If -Ipipe the file descriptor connected to stdin of the program, otherwise empty.
  • <stdout> - If -Opipe the file descriptor connected to stdout of the program, otherwise empty.
  • <stderr> - If -Epipe the file descriptor connected to stderr of the program, otherwise empty.
  • <cmd...> - The %q escaped command that was executed.

You should use getters L_proc_get_* to extract the data from proc variable. The proc variable is not an array, so it can be used in an array to run many processes.

Example

  L_proc_popen -Ipipe -Opipe proc sed 's/w/W/g'
  L_proc_printf proc "%s\n" "Hello world"
  L_proc_read proc line
  L_proc_wait -c -v exitcode proc
  echo "$line"
  echo "$exitcode"

Options:

  • -I <str> stdin mode
  • -i <str> string for -Iinput, file for -Ifile, fd for -Ifd
  • -O <str> stdout mode
  • -o <str> file for -Ifile, fd for -Ifd
  • -E <str> stderr mode
  • -e <str> file for -Efile, fd for -Efd
  • -n Dryrun mode. Do not execute the generated command. Instead print it to stdout.
  • -W <int> Register with L_finally a return trap on stacklevel that will wait for the popen to finish. Typically -W 0
  • -h Print this help and return 0.

Arguments:

  • $1 variable name to store the result to.
  • $@ command to execute.

L_proc_get_exitcode

Get exitcode of L_proc.

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 L_proc variable

L_proc_get_exitcode_v

L_proc_get_pid

Get PID of L_proc.

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 L_proc variable

L_proc_get_pid_v

L_proc_get_stdin

Get file descriptor for stdin of L_proc.

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 L_proc variable

L_proc_get_stdin_v

L_proc_get_stdout

Get file descriptor for stdout of L_proc.

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 L_proc variable

L_proc_get_stdout_v

L_proc_get_stderr

Get file descriptor for stderr of L_proc.

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 L_proc variable

L_proc_get_stderr_v

L_proc_get_cmd

Get command of L_proc.

Option: -v <var> Store the output in variable instead of printing it.

Argument: $1 L_proc variable

L_proc_get_cmd_v

L_proc_popen_finally

Handler that can be closed from L_finally or a signal handler.

Closes file descriptors. If L_SIGNAL is a signal, forwards it to the process. Then wait for the process termination.

Example

L_finally proc -W sleep infinity

Example

   L_finally proc sleep infinity
   L_finally L_proc_popen_finally "$proc"

   # or
   L_finally proc sleep infinity
   L_finally L_eval 'L_proc_popen_finally "${!1}"' proc

Argument: $1

L_proc value. This is because the variable may go out of scope.

This is bad. when closing a file descriptor, we "remember" that the file descriptor was closed in the variable. This is less then ideal, but I do not know at this time how to fix it better. Potentially, this can cause unrelated file descriptors to get closed. This might change in the future.

L_proc_printf

Write printf formatted string to coproc.

Arguments:

  • $1 L_proc variable
  • $@ any printf arguments

L_proc_read

Exec read bultin with -u file descriptor of stdout of coproc.

Arguments:

  • $1 L_proc variable
  • $@ any builtin read options

L_proc_read_stderr

Exec read bultin with -u file descriptor of stderr of coproc.

Arguments:

  • $1 L_proc variable
  • $@ any builtin read options

See: L_proc_read

L_proc_close

Close stdin, stdout and stderr of L_proc

Argument: $1 L_proc variable

L_proc_close_stdin

Close stdin of L_proc.

Does nothing if already closed or not started with -Opipe.

Argument: $1 L_proc variable

L_proc_close_stdout

Close stdout of L_proc.

Does nothing if already closed or not started with -Opipe

Argument: $1 L_proc variable

L_proc_close_stderr

Close stderr of L_proc.

Does nothing if already closed or not started with -Epipe.

Argument: $1 L_proc variable

L_proc_poll

Check if L_proc is finished.

Argument: $1 L_proc variable

Exit: 0 if L_proc is running, 1 otherwise

L_wait

Wait for pids to be finished with a timeout and capture exit codes.

Tries to use waitpid or tail --pid or a busy loop for best performance.

The waiting is uninterruptible by signals.

Note: builtin kill with multiple pids has different exit code depending on posix mode.

Options:

  • -t <timeout> Wait for this long. Timeout 0 results in just collecting all pids.
  • -v <var> Exit code of PIDs will be assigned to . The elements of -v and -p arrays are pairs.
  • -p <var> PIDs that exited will be assigned to array variable .
  • -l <var> Left running PIDs will be assigned to array variable .
  • -P <polltime> The time to poll processes when not possible to use waitpid or tail. Default: 0.1
  • -n Return 0 when at least one of the pids is finished.
  • -b Bash only. Do not use waitpid or tail.
  • -h Print this help and exit.

Argument: $@ pids to wait on

Return:

0 on success

    2 usage error
    124 timeout

L_proc_wait

Wait for L_proc to finish.

If L_proc has already finished execution, will only evaluate -v option.

Options:

  • -t <int> Timeout in seconds. Will try to use waitpid, tail --pid or busy loop with sleep.
  • -v <var> Store the output in variable instead of printing it.
  • -c Close L_proc file descriptors before waiting.
  • -h Print this help and return 0.

Argument: $1 L_proc variable

Exit: 0 if L_proc has finished, 1 if timeout expired

L_read_fds

Read from multiple file descriptors at the same time.

Note

The minimum read -t argument in Bash3.2 is 1 second. It is not possible

to set it lower or to a fraction. This does not work great for Bash3.2 for short timeout, as one read takes at least 1 second to execute.

Example

  exec 10< <(for ((i=0;i<5;++i)); do echo $i; sleep 1; done)
  exec 11< <(for ((i=0;i<5;++i)); do echo $i; sleep 2; done)

Options:

  • -t <timeout> Timeout in seconds.
  • -p <timeout> Poll timeout. The read -t argument value. Default: 0.05 or 1 in Bash3.2
  • -h Print this help and return 0.
  • -n <var> When the first fd errors or becomes EOF and assign it's number to and return 0.
  • -C <callback>

    Each time any chunk of data is read,

           evaluate the expression "<callback> <fd> <variable> <line>".
    
  • -d <delim> Read -d argument. Default: ''
  • -1 Run the loop until all file descriptors timeout.

Arguments:

  • $1 File descriptor to read from.
  • $2 Variable to assign the output of $1.
  • $@ Continued pairs of file descriptor and variable names.

Return:

0 on success

    124 on timeout

L_proc_communicate

Communicate with L_proc.

Options:

  • -i <str> Send string to stdin.
  • -o <var> Assign stdout to this variable.
  • -e <var> Assign stderr to this variable.
  • -t <int> Timeout in seconds.
  • -k Kill L_proc after communication.
  • -v <var> Store the output in variable instead of printing it.
  • -h Print this help and return 0.

Argument: $1 L_proc variable

Exit: 0 on success. 2 on invalid options. 124 on timeout.

L_proc_send_signal

Send signal to L_proc.

Arguments:

  • $1 L_proc variable
  • $2 signal to send

L_proc_terminate

Terminate L_proc.

Argument: $1 L_proc variable

L_proc_kill

Kill L_proc.

Argument: $1 L_proc variable

lib

internal functions and section.

Internal functions to handle terminal interaction.