You have a directory full of files on your Linux system that you would like to burn to a CD.
Do you need an expensive CD burning program, or can you do it with the shell and some open source programs?
You can do it with two open source programs called mkisofs and cdrecord, and a bash script to help you keep all the options straight.
Start by putting all the files that you want to copy to CD into a directory structure.
The script will take that directory, make an ISO filesystem image from those files, then burn the ISO image.
All it takes is a bunch of disk space and a bit of time—but you can get up and wander while the bash script runs.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
1 #!/usr/bin/env bash 2 # cookbook filename: cdscript 3 # cdscript - prep and burn a CD from a dir. 4 # 5 # usage: cdscript dir [ cddev ] 6 # 7 if [[ $# < 1 || $# > 2 ]] 8 then 9 echo 'usage: cdscript dir [ cddev ]' 10 exit 2 11 fi 12 13 # set the defaults 14 RCDIR=$1 15 # your device might be "ATAPI:0,0,0" or other digits 16 CDDEV=${2:-"ATAPI:0,0,0"} 17 ISOIMAGE=/tmp/cd$$.iso 18 19 echo "building ISO image..." 20 # 21 # make the ISO fs image 22 # 23 mkisofs $ISOPTS -A "$(cat ~/.cdAnnotation)" \ 24 -p "$(hostname)" -V "$(basename $SRCDIR)" \ 25 -r -o "$ISOIMAGE" $SRCDIR 26 STATUS=$? 27 if [ $STATUS -ne 0 ] 28 then 29 echo "Error. ISO image failed." 30 echo "Investigate then remove $ISOIMAGE" 31 exit $STATUS 32 fi 33 34 echo "ISO image built; burning to cd..." 35 exit 36 37 # burn the CD 38 SPD=8 39 OPTS="-eject -v fs=64M driveropts=burnproof" 40 cdrecord $OPTS -speed=$SPD dev=${CDDEV} $ISOImage 41 STATUS=$? 42 if [ $STATUS -ne 0 ] 43 then 44 echo "Error. CD Burn failed." 45 echo "Investigate then remove $ISOIMAGE" 46 exit $STATUS 47 fi 48 49 rm -f $ISOIMAGE 50 echo "Done." |
Here is a quick look at some of the odder constructs in this script.
At line 17:
1 |
17 ISOIMAGE=/tmp/cd$$.iso |
we construct a temporary filename by using the $$ variable, which gives us our process number.
As long as this script is running, it will be the one and only process of that number, so it gives us a name that is unique among all other running processes.
In line 26, we save the status of the mkisofs command. Well-written Unix and Linux commands (and bash shell scripts) will return 0 on success (i.e., nothing went wrong) and a nonzero value if they fail.
We could have just used the $? in the if statement on line 27 except that we want to preserve the status from the mkisofs command so that, in the event of failure, we can pass that back out as the return value of this script (line 31).
We do the same with the cdrecord command and its return value on lines 41–47.
It may take a bit of thought to unpack lines 23–25:
1 2 3 |
23 mkisofs $ISOPTS -A "$(cat ~/.cdAnnotation)" \ 24 -p "$(hostname)" -V "$(basename $SRCDIR)" \ 25 -r -o "$ISOIMAGE" $SRCDIR |
All three lines are just a single line of input to bash which has been separated across lines by putting the backslash as the very last character on the line in order to escape the normal meaning of an end of line.
Be sure you don’t put a space after the trailing \. But that’s just the tip of the iceberg here.
There are three subshells that are invoked whose output is used in the construction of the final command line that invokes mkisofs.
First there is an invocation of the cat program to dump the contents of a file called .cdAnnotation located in the home directory (~/) of the user invoking this script.
The purpose is to provide a string to the -A option, which the manpage describes as “a text string that will be written into the volume header.”
Similarly, the -p option wants another such string, this time indicating the preparer of the image.
For our script it seemed like it might be handy to put the hostname where the script is run as the preparer, so we run hostname in a subshell.
Finally, the volume name is specified with the -V parameter, and for that we will use the name of the directory where all the files are found.
Since that directory is specified on the command line to our script, but will likely be a full pathname, we use basename in a subshell to peel off the leading directory pathname, if any (so, for example, /usr/local/stuff becomes just stuff).