Last active
January 24, 2025 22:05
-
-
Save joehillen/30f08738c1c3c0ca3e4c754ad33ad2ff to your computer and use it in GitHub Desktop.
Build bash scripts with `source` files into a single script.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# | |
# https://gist.github.com/joehillen/30f08738c1c3c0ca3e4c754ad33ad2ff | |
# | |
# This script inlines 'source' files. | |
# | |
# For long scripts, it is nice to be able to break them into multiple files | |
# to make them easier to work with but still release as a single script. | |
# | |
# Inspired by https://stackoverflow.com/a/37533160/334632 with the following enhancements: | |
# - supports sourcing files with quotes, spaces, and ~. | |
# - supports sources in sources | |
# - inline scripts from $PATH | |
# - errors on (mutual) recursion | |
# - preserves indentation | |
# - omits shebangs in sourced files | |
# | |
# This will NOT work with variables in source paths. | |
# | |
# WARNING MacOS users: Requires a modern version of Bash | |
set -e | |
set -o pipefail | |
declare -A sourced | |
function _inline_sources { | |
while IFS='' read -r line; do | |
if [[ $line =~ ^([[:space:]]*)(source|\.)[[:space:]]+(.+) ]]; then | |
indent=${BASH_REMATCH[1]} | |
source_command=${BASH_REMATCH[2]} | |
file=${BASH_REMATCH[3]} | |
echo "${indent}# $source_command $file" | |
if [[ $file != */* ]]; then | |
fp=$(type -p "$file" || :) # look in $PATH | |
fi | |
if [[ -z $fp ]]; then | |
fp=$(eval realpath "$file") # resolve links, relative paths, ~, quotes, and escapes. | |
fi | |
# fail if we've already sourced this file | |
if [[ ${sourced[$fp]} = 1 ]]; then | |
echo "ERROR: Recursion detected: $fp" | |
exit 1 | |
fi | |
sourced["$fp"]=1 | |
_inline_sources "$fp" | sed -e "/^#!.*/d;s/^/${indent}/" # remove shebang and add indentation | |
sourced["$fp"]=0 | |
continue | |
fi | |
echo "$line" | |
done < "$1" | |
} | |
_inline_sources "$1" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
the script from https://stackoverflow.com/a/37533160 (just wrapped it into a function like yours)
sadly your script includes the first sourced file for all further sources.
test.sh