How can I add an audio file (OGG vorbis) into a shell script making the script as small as possible and at the same time being able to execute it on as most systems as possible? I want the audio file be played.

I don’t want it to be uuencoded, because sharutils are not installed on many systems. base64 is nice, but makes the file/script bigger, which I don’t want.

Should I use mplayer or the play command from the sox package? Is it more common on Linux/BSD systems? Or is there another media player mostly installed? Should I convert the audio file to another format/codec (if that doesn’t make the file much bigger) to have more possible players to play the file back or is OGG vorbis a good choice?


With the following script it works (using mplayer, which is probably not present on many systems).

grep -A 1000 --text -m 1 ^Ogg "$0" | mplayer -

The last line is the beginning of the audio file binary.

The grep command searches for the first occurrence of Ogg in the file $0 (which is the script file itself) and prints 1000 lines after that line (is enough for my small audio test file). The output of grep is then piped to mplayer which is reading /dev/stdin (abbreviation for /dev/stdin is -).

I have created this file by concatenating the script file playmeBashScript.sh with the audio file sound.ogg:

cat playmeBashScript.sh sound.ogg > playme.sh

A more general and a bit shorter version with sed instead of grep (thanks to Elias):

sed 1,/^exit$/d "$0" | mplayer -

In this case sed selects all lines from number one up to the line where it finds the word exit and deletes them. The rest is pasted and piped to mplayer. Of course that only works if the word exit occurs only once in the script before the binary data.

  • It will probably be better to use sed 1,/^Ogg/d "$0" | mplayer - instead.
    – elias
    Feb 7 '14 at 16:24
  • @elias no that does not work. The Ogg is part of the audio file (the first three bytes of it) and your command deletes this line (as far as I understand it). If I apply your command to my playme.sh file, the output is to small, does not play.
    – erik
    Feb 7 '14 at 16:42
  • 1
    oh, alright, then maybe using another separator and then using: sed 1,/^BEGIN_FILE/d "$0" | mplayer -. I just thought it could be a more general solution. =)
    – elias
    Feb 7 '14 at 16:44
  • Yes, ok. That is more general than having to tweak the number of output lines at grep’s -A option. I will change my answer.
    – erik
    Feb 7 '14 at 16:46

Your script should contain also the concatenated data:


trap "rm ${TMPFILE}" 0 1 2 3 11 15
tail -n +7 $0 ${TMPFILE}
exec mplayer ${TMPFILE}

Let's call the script omniplay. So you need to cat your ogg-file appending to the script:

cat file.ogg >> omniplay
chmod +x omniplay

This is a standard method used by many install.sh files. Look also for gzexe. You may also adjust the tail lines.

  • Has your version any advantages over my version? I don’t like it because it is longer. And I’d rather read the data directly from the file instead of writing it into a temporary file. Imagine the media file is 10 GB in size. Not a good idea to put that into a temporary file first.
    – erik
    Feb 7 '14 at 17:06

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.