0

I have a fairly large BASH project, which I split into multiple files to make it more readable. As a result, the main file contains many source statements.

Now I'm releasing it on GitHub and I'm writing an installer script for it. The problem is that creating subdirectories under binary folders (exactly /usr/local/sbin) is prohibited by the FHS and I don't want to mess up binary folders with several files like main.bash config.bash, etc.

As a solution, I thought that if the installer script would merge together these files, I'd get a large, monolithic BASH file, which can be put anywhere on the system.

The question is: how can I substitute all source statements in my main script with the contents of the sourced files?

Example:

included.bash

echo "bar"

main.bash

echo "foo"
source included.bash

Resulting monolithic file

echo "foo"
echo "bar"
1
  • Why not in /usr/local/lib/<yourprogramname> instead?
    – didierc
    Commented Jun 28, 2014 at 19:23

1 Answer 1

1

This script, which might be called make-monolithic.bash, will walk through each line in main.bash and look for a source statement. If there's no match it will just copy that line to the monolithic.bash file. However if a source line is found, the filename is extracted and the contents of that file will be copied to monolithic.bash, instead of the original source line.

#!/usr/bin/env bash

readonly MAIN="main.bash"
readonly MONOLITHIC="monolithic.bash"

[ -f "$MONOLITHIC" ] && cp "$MONOLITHIC" "${MONOLITHIC}.bak"

## to extract sourced filename
regex='^\([[:space:]]*\)source[[:space:]]\+\([^[:space:]]\+\)[[:space:]]*$'

IFS=$'\n'  ## retain whitespace

while read main_line; do
    sourced=$(echo "$main_line" | sed -n "s/$regex/\2/p")
    if [ -n "$sourced" ]; then
        indent=$(echo "$main_line" | sed -n "s/$regex/\1/p")
        while read sourced_line; do
            echo "${indent}${sourced_line}" >> "$MONOLITHIC"
        done < "$sourced"
    else
        echo "$main_line" >> "$MONOLITHIC"
    fi
done < "$MAIN"

unset IFS

[ -f "${MONOLITHIC}.bak" ] && rm "${MONOLITHIC}.bak"
  • tested on your provided example
  • also gracefully ignores possible whitespace issues in the source line
  • plus: automatically applies the same amount of indentation to the contents of the sourced file as found before the source statement (none, if source line was not indented, as in your example)

You must log in to answer this question.

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