0

I have multiple bash scripts and resources required by these scripts (like music files and images) and I want to pack them all into one executable file.

For example:

$ find Scripts/

Scripts/
Scripts/main.sh
Scripts/bin/1.sh
Scripts/bin/2.sh
Scripts/src/music.mp3

Now, I want to pack all these into one executable which if I execute, executes the Scripts/main.sh file.

How can I do that?

Spiff
  • 101,729
  • 17
  • 175
  • 229
Random Guy
  • 5
  • 1
  • 4
  • How does one script (e.g. `main.sh`) call or source another? If by its absolute path then there's a problem; If by its relative path then there's another problem. If by `$PATH` then another. One solution I can think of is refactoring code, so dependent files just define shell functions, `main.sh` sources them all and uses the functions. Then it's relatively easy to replace `. …`/`source …` with actual content (definitions) to get one big standalone `main.sh`. – Kamil Maciorowski Oct 05 '22 at 15:08
  • Does [this post](https://superuser.com/questions/42788/is-it-possible-to-execute-a-file-after-extraction-from-a-7-zip-self-extracting-a) using 7Zip solve your problem? – harrymc Oct 05 '22 at 15:46
  • What is the motivation here? It is for distributing the "package" in one file that the user just has to execute? Other? – PierU Oct 05 '22 at 16:44

1 Answers1

1

One way is to use the Shell Archive (shar) utility. It is maybe not installed by default, but likely present in the repository of your distribution.

Very much like tar it can create an single-file archive of a list of files. The difference is that the archive file is self-extracting: this is a shell script that has to be run.

In your case :

shar -M -D -Q Scripts/ > myarchive.sh packs the whole Scripts/ folder into myarchive.sh.

Then you can pass myarchive.sh to someone else. By running sh myarchive.sh he will locally unpack Scripts/ and all its content.

But this is not enough, as you also want to execute Scripts/main.sh . You have then to add this command at the end of myarchive.sh, and the full command is:

shar -M -D -Q Scripts/ | head -n -1 > myarchive.sh && echo "Scripts/main.sh" >> myarchive.sh

The purpose of head -n -1 is to remove the last line of the archiv, which is exit 0, otherwise the command you are adding won't be executed. I haven't tested since this syntax doesn't work on macOS (I used grep -v "exit 0"instead, but there can be edge effects with that).

Now Scripts/main.sh will be executed once the archive is unpacked.

I couldn't solve a (small) problem: the -Q option is supposed to make the unpack stage quiet, without output messages. But there are still some of them, I don't why...

PierU
  • 1,539
  • 5
  • 20