Bash script to create another bash script?

Hey folks, I am currently developing on my own bash script and would like to extend it with a function where code that I already have will be placed into a second bash file without being executed. The whole thing looks somewhat like this:


#!/bin/bash

echo "Hey, I am the main script!"
...
cat > /home/$USER/bin/SECOND_SCRIPT << EOT

#!/bin/bash

    # - This shall be the second script which automaticall gets placed elsewhere
    # - This shall not be executed when executing the main script
    # - Code within this script shall not appear within the terminal of the main script

    # Settings

    LOCALMUSIC="$HOME/Music"
    ALERT="/usr/share/sounds/pop.wav"
    PLAYER="mpv --vo null"

(more lines of code here)

EOT

# Continuing with stuff of the main script
...

My main Issue with creating this neat piece of my script is that code from the second script gets displayed and executed within the terminal window of the first main script. So, how would YOU accomplish this task? Is there some code snipped I missed to insert?

Your script sort-of works for me.

I took your script, and dumped it into a file. I changed the line “…” to “echo …” and I changed the line
“# Continuing with stuff of the main script” to “echo ‘# Continuing with stuff of the main script’”

Then I ran it. I did not see code from the second script. If I had use “bash -x” to test it, then I expect I would have seen some of that – it’s what “-x” does.

One problem, though. You need to remove that blank line immediately after the “cat” command. Otherwise the blank line goes into the file, so that the “#!/bin/bash” is on the second line rather than the first line.

Also, why do you use “/home/$USER/bin/SECOND_SCRIPT” instead of “$HOME/bin/SECOND_SCRIPT”?

I did a try here, but copy/paste of your script gives problems because you inserted things like

...

and

(more lines of code here)

Which means that you did not provide us with the exact case that you say does not function. >:)

So I did this:

henk@boven:~/test/oo> ls -l
totaal 4
-rwxr--r-- 1 henk wij 511 24 mei 20:33 sc
henk@boven:~/test/oo> cat sc
#!/bin/bash

echo "Hey, I am the main script!"

cat > SECOND_SCRIPT << EOT

#!/bin/bash

    # - This shall be the second script which automaticall gets placed elsewhere
    # - This shall not be executed when executing the main script
    # - Code within this script shall not appear within the terminal of the main script

    # Settings

    LOCALMUSIC="$HOME/Music"
    ALERT="/usr/share/sounds/pop.wav"
    PLAYER="mpv --vo null"

(more lines of code here)

EOT

# Continuing with stuff of the main script
henk@boven:~/test/oo> ./sc
Hey, I am the main script!
henk@boven:~/test/oo> ls -l
totaal 8
-rwxr--r-- 1 henk wij 511 24 mei 20:33 sc
-rw-r--r-- 1 henk wij 393 24 mei 20:35 SECOND_SCRIPT
henk@boven:~/test/oo> cat SECOND_SCRIPT

#!/bin/bash

    # - This shall be the second script which automaticall gets placed elsewhere
    # - This shall not be executed when executing the main script
    # - Code within this script shall not appear within the terminal of the main script

    # Settings

    LOCALMUSIC="/home/henk/Music"
    ALERT="/usr/share/sounds/pop.wav"
    PLAYER="mpv --vo null"

(more lines of code here)

henk@boven:~/test/oo> 

And I have the idea that it does what you think it should do.

So minimising your test case to check if it functions basicaly is OK. But then you should present something that illustrates what you say. Else finding erorrs in te script is a bit difficult (understatement ;)).

Without knowing what else is in your script, the only thing I might suggest you should be aware of is that if you use cat to declare code blocks multiple times, you need to use a different delimiter (you used EOT in your posted code) each time.

TSU

On 2014-05-24 20:46, nrickert wrote:
> Then I ran it. I did not see code from the second script. If I had use
> “bash -x” to test it, then I expect I would have seen some of that –
> it’s what “-x” does.

Instead of calling the second script, you can call “xterm” and tell it
to run the second script. That way it gets its own separate window -
which will die and close as soon as the secondary script finishes,
unless you take steps against it (like calling “read”).

I do something like that in order to process long jobs, generating one
task per cpu core. It works better than telling some processes to work
multithreaded (depends on the code).


Cheers / Saludos,

Carlos E. R.
(from 13.1 x86_64 “Bottle” at Telcontar)

On Sat, 24 May 2014 16:56:02 +0000, SecUpwN wrote:

> Hey folks, I am currently developing on my own bash script and would
> like to extend it with a function where code that I already have will be
> placed into a second bash file without being executed.

Check the bash man page for the “source” builtin command. You can define
functions in an external script file, “source” the file in your main
script, and call those functions. It’s a pretty common practice.

Jim


Jim Henderson
openSUSE Forums Administrator
Forum Use Terms & Conditions at http://tinyurl.com/openSUSE-T-C

Just keep in mind that sourcing a file is the same thing as running what ever is inside that file, like what Jim said put functions or aliases or variables in there. Don’t put commands that are not inside a function or alias, specially if the commands involves rm ;).
Let us put that to the test shall we?

Create a directory for testing.

jetchisel@localhost:~> mkdir testing && cd "$_"

jetchisel@loclhost:~/testing>

Now create your file that you want to source and put some variables and function in it.

jetchisel@localhost:~/testing> printf '%s
'  'foo=hello'  'bar=world'  'qux() { echo 'Hi i am the function named qux; }'   > File

check that file if it is created.

jetchisel@localhost:~/testing> ls
File

Check what is inside the file.


jetchisel@localhost:~/testing> cat File

foo=hello
bar=world
qux() { echo "Hi i am the function named qux"; }

Now source it.

jetchisel@localhost:~/testing> source File

You have those variables and function available. let us test it.

jetchisel@localhost:~/testing> echo "$foo"
hello


jetchisel@localhost:~/testing> echo "$bar"
world

jetchisel@localhost:~/testing> qux
Hi i am the function named qux

Now let us add rm to that file.

jetchisel@localhost:~/testing> echo 'rm -rf *' >> File

that File should still be in your directory we just added the rm -rf * as the last line.

jetchisel@localhost:~/testing> ls 
File

jetchisel@localhost:~/testing> cat File
foo=hello
bar=world
qux() { echo "Hi i am the function named qux"; }
rm -rf *

source it again.

jetchisel@localhost:~/testing> source File

Now run ls

jetchisel@localhost:~/testing> ls

Congratulations you just deleted the File inside the ~/testing directory :wink:

Quoting failure on that part sorry :(, this should work now.

jetchisel@localhost:~/testing> printf '%s
'  'foo=hello'  'bar=world'  'qux() { echo "Hi i am the function named qux**"**; }'   > File

A general comment on this idea of invoking a completely separate BASH script,

I doubt that should be necessary or even desirable, unless you have an issue running all your code as one process I don’t know you should be creating another process to execute something related to what is happening in the first process (script).

Instead,
I should think that you ought to simply organize your code in code blocks, and manage how they run as a single script.

IMO,
TSU