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"
  • Why not in /usr/local/lib/<yourprogramname> instead? – didierc Jun 28 '14 at 19:23
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)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.