Bash: How can a script create a script?

I need to write a bash script that will generate another bash script. Furthermore, the child script is required to be hard-coded into the parent script. The parent script is not allowed to import the child script from an external file at run time. If you have a better solution than the following, please let me know.

I tried "cat" in the following manner.

cat > child.sh << EOF
The content of child script
...
...
EOF

However, if the child script contains variables, command substitutions and backtick pipes as shown below, then bash will expand them when the parent script is executed. Thus, the resultant child script will be corrupted and differ from the original child script.

cat > child.sh << EOF
#...
#...
OriginalDir=$(pwd)  #command substitution
cd $CloudDir        #variable
Array=`ls -1 *.txt` #backtick pipe
cd $OriginalDir     #variable
#...
#...
EOF

So, I have to somehow disable variable expansion, command substitution and backtick pipe. I thought about single quotes to disable expansion.

echo '.......' > child.sh
echo '.......' >> child.sh
echo '.......' >> child.sh

However, if the original child script contains single quotes, they will interfere with the outer single quotes, and hence the resultant child script will corrupt. Single quotes do not work.

In the above cat method, the expansion were interfering with $ and `. Now, my workaround is to temporarily remove $ and ` by applying percent-encoding to $ and `. That is, $ is replaced with %24, and ` is replaced with %60, (after % is replaced with %25 first) before the child script is embedded into the parent script. All the other characters are intact. Thus, the child script is prepared by sed like below.

sed "s/%/%25/g" | sed 's/\$/%24/g' | sed 's/`/%60/g'

At run time, the parent script will decode percents and restore the original version of the child script by piping the output from cat to sed in the following manner.

cat << EOF | sed 's/%60/`/g' | sed "s/%24/$/g" | sed "s/%25/%/g" > child.sh
#...
#...
OriginalDir=%24(pwd)    #command substitution
cd %24CloudDir          #variable
Array=%60ls -1 *.txt%60 #backtick pipe
cd %24OriginalDir       #variable
#...
#...
EOF

In this last method, the percent-encoding protects the variables, command substitutions and backtick pipes in the child script from expansion. However, the percent-encoding modifies the child script, even though the modification is temporary and the original version will be restored at the end. I prefer not to modify the child script at all.

In bash, how can a parent script generate a child script without the kind of preparation that modifies the child script? Does anyone know how to protect the variables, command substitutions and backtick pipes in the child script from expansion without encoding the child script? Note again that the child script is required to be hard-coded into the parent script. The parent script is not allowed to import the child script from an external file at run time. Any idea?

Many thanks in advance.

Check the << bit of your bash man pages.
If you quote any part of the here document terminator it disables parameter substitution within the here document:

cat > child.sh << \EOF

The other approach is to escape any Shell special characters:
e.g.

echo \$PATH

Quite handy if you are embedding Oracle SQL.

1 Like

There's a neat little trick the shell allows you to use. Compare these 2 runs:

$ var=foo
$ cat << EOF
> echo $var
> EOF
echo foo
$ cat << 'EOF'
> echo $var
> EOF
echo $var
1 Like

Any particular reason you want to generate a script in a script? Sometimes there's better ways, if you'll tell us the goal rather than the method you want.