The LED-version Planck-constant lab is very intensive in data analysis, requiring that you make three
graphs per LED, 21 graphs, plus the final frequency versus V min plot. Shell scripts or batch files are used
for massively repetitive file analysis, or conversion, or production. In a shell script you use the login shell
of the computer as a programmable interpreter.
All shell scripts begin with the line
#!/bin/sh
|
and are made executable by (saving them with a name such as “script.sh”) and running
chmod a+x script.sh
|
on them. The syntax of a bash shell script is rather particular, but is quite like C syntax. The best way to
learn scripting is by example.
Suppose that in the nuclear counting experiment you create a data file in which each line is the number of
counts in a ten second interval. To sort this into a frequency plot of the number of occurances of each
count we use a script containing an AWK routine, and pipes of the output into the uniq, sort, and graph
commands. If your MinGW or MSYS installation does not have sort or uniq, you can get a coretils
package from http://gnuwin32.sourceforge.net/ that contain both. Read the man pages for command
line switches and instructions.
#!/bin/sh
# reads in a file of numbers and sorts x, 0<= x<= 11 # them into a frequency plot # and graphs it awk ’{ i=0 while ( i<11 ) { if ( $1 ==i ) print i ++i} }’ $1 | sort -n | uniq -c | awk ’{print $2, " ", $1}’ | graph -T X |
The script below is an automatic conversion utility that will accept any file of types .c, .cc, .h, .f, .txt, .tex, .pdf, .ps, .gif, .jpg, .html and will perform the conversion into postscript automatically, and print the converted file. You can use it by simply typing
Print filename
|
of course giving it the correct filename for the file you wish to print. The script illustrates how to program
the shell to accept input that is switched on using cases. The script invokes a number of common UNIX
text programs such as file, ps2pdf, enscript, lp and others.
#!/bin/sh
# file type detection and print filter for i in .ps .dvi .f .cc .c .h .tex .gif .jpg .html .gz .tgz .bz2 .pdf do base=$(basename $1 $i) if [ $1 = $base$i ] then # determine file type type=$i fi done # now do something case "$type" in ".ps" ) echo $1 is a postscript file echo Printing lp $1 ;; ".dvi") echo $1 is a dvi file echo Converting to postscript with dvips base=$(basename $1 .dvi) dvips -o ${base}.ps $1 echo Printing and removing the postscript file # lp ${base}.ps # rm ${base}.ps ;; ".tex") echo $1 is a tex file, converting to postscript base=$(basename $1 .tex) enscript -p ${base}.ps $1 echo Printing and removing the postscript file # lp ${base}.ps # rm ${base}.ps ;; ".pdf") echo Ahh, a PDF file, converting to postscript and printing base=$(basename $1 .pdf) pdf2ps $1 ${base}.ps # lp ${base}.ps # rm ${base}.ps ;; ".html") echo Open this file with Mozilla, print it to echo a postscript file, and print that ;; ".gz" | ".tgz" | ".bz2" ) echo This is a compressed archive ;; ".c") echo $1 is a C source file echo Converting to postscript enscript -p $1.ps $1 echo Printing and removing the postscript file # lp $1.ps # rm $1.ps ;; ".cc") echo $1 is a C++ source file echo Converting to postscript enscript -p $1.ps $1 echo Printing and removing the postscript file # lp $1.ps # rm $1.ps ;; ".f") echo $1 is a FORTRAN77 source file echo Converting to postscript enscript -p $1.ps $1 echo Printing and removing the postscript file # lp $1.ps # rm $1.ps ;; ".h") echo $1 is a C header file echo Converting to postscript enscript -p $1.ps $1 echo Printing and removing the postscript file # lp $1.ps # rm $1.ps ;; * ) echo I dont know what this shit is echo Sorry, I dont know what to do with it ;; esac |
This shell script illustrates how the shell bash can actually be programmed, or rather used as an
interpreter. Each line of the script is a command interpreted by bash, and the shell understands loop,
conditionals, cases, and integer arithmetic. This shell script invokes the commands echo, basename,
dvips, enscript, lp, convert, rm and dvips. In other words a script is a collection of commands that
you would normally type into the shell and execute one by one, the script simply automates
them.
Below is a short example script that converts all .fig files in your working directory into .gif images, with
the color white being made transparent.
#!/bin/bash
#shell script for fig --> gif conversion with white transparency for file in $(ls *.fig) do echo $file base=$(basename $file .fig) echo $base convert $file $base.ppm /usr/local/netpbm/ppmtogif -trans "#FFFFFF" $base.ppm > $base.gif done exit 0 |
The script below will accept a command-line option, your system type, and create a makefile for compiling
all C-sources in your working directory.
#!/bin/sh
# Uncle Jeff’s handy Makefile generator script for multi-file projects echo \# Makefile for Graphics programs echo \# you may need to adjust the FLAGS or CFLAGS variable echo \# depending on whether you are building g2 or libplot programs printf " \n\n" type=$1 case "$type" in "win" | "Win" | "w" | "W" | "win32" | "evil") echo SUFFIX = ".exe" SUFFIX=".exe" echo CPATH = /usr/local/cross-tools/bin/ echo LPATH = /usr/local/cross-tools/lib/ echo LPATH2 = /usr/local/cross-tools/i386-mingw32msvc/lib/ echo IPATH = /usr/local/cross-tools/include/ echo IPATH2 = /usr/local/cross-tools/i386-mingw32msvc/include/ echo ’CC = $(CPATH)/i386-mingw32msvc-gcc’ echo ’GCC = $(CPATH)/i386-mingw32msvc-gcc’ echo ’CXX = $(CPATH)/i386-mingw32msvc-g++’ echo ’G77 = $(CPATH)/i386-mingw32msvc-g77’ echo ’CPP = $(CPATH)/i386-mingw32msvc-cpp’ echo ’LD = $(CPATH)/i386-mingw32msvc-ld’ echo ’AR = $(CPATH)/i386-mingw32msvc-ar’ echo ’AS = $(CPATH)/i386-mingw32msvc-as’ echo FLAGS = -O2 -fomit-frame-pointer -static echo CFLAGS = -static -O2 -DPFD_DOUBLEBUFFER=1 -DTBSTYLE_EX_DOUBLEBUFFER=1 -DUNIX=1 -DX_DISPLAY_MISSING=1 -DDO_WIN32=1 -DHAVE_LIMITS_H=1 -DWIN32 -DPDCURSES -D__MINGW32__ echo ’LDFLAGS = -I$(IPATH) -I$(IPATH2) -L$(LPATH) -L$(LPATH2) -lpdcurses -lg2 -lm -lkernel32 -lgdi32 -lmsvcrt -luser32 -lcomdlg32’ echo GMPFLAGS = -lpdcurses -lm -lgmp echo LDXFLAGS = -lpdcurses -lplot -lpng -lz -lm ;; "linux" | "Linux" | "l" | "L" | "unix" | "good" | "mingw" | "Mingw") echo CC = /usr/bin/gcc echo CPP = /usr/bin/cpp echo \# Change suffix to .exe for mingw echo SUFFIX = "" case "$type" in "mingw" | "Mingw") SUFFIX=".exe" echo CFLAGS = -static -O2 -DPFD_DOUBLEBUFFER=1 -DWIN32 -DDO_WIN32=1 echo \# uncomment one of these; echo \# mingw LDFLAGS for libplot programs echo \#LDFLAGS = -lplot -lpng -lz -lm echo \# mingw LDFLAGS for g2 programs echo \#LDFLAGS = -lg2 -lm -lkernel32 -lgdi32 -lmsvcrt -luser32 -lcomdlg32 ;; "linux" | "Linux" | "l" | "L" | "unix") SUFFIX="" echo CFLAGS = -DXWIN -O2 -fomit-frame-pointer echo LDFLAGS = -L/usr/X11R6/lib -I/usr/X11R6/include -lplot -lXaw -lXmu \\ printf "\t-lXt -lSM -lICE -lXext -lX11 -lm -lcurses -lgd -lg2\n" ;; esac ;; *) echo "Not a valid target" echo "pick from win, Win, win32, Linux, unix, linux, mingw, Mingw" exit 0 ;; esac printf "\n\n# targets\n\n" printf "all: \t" for file in $(ls *.c); do base=$(basename $file .c) printf "%s " "$base$SUFFIX" done printf "\n\n" # targets for file in $(ls *.c); do base=$(basename $file .c) printf "%s\n" "$base$SUFFIX: $file" printf "\t%s\n" "\$(CC) \$(CFLAGS) $file \$(LDFLAGS) -o $base$SUFFIX" printf "\n" done |
The LED Planck law can be easily analyzed by saving the I versus V data for each LED under a filename,
for example use the LED wavelength in nanometers as the filename, such as “586.raw”. Write a program
that reads this in, and creates several related files, such as
586.diff, a table of
versus I,
586.diff.line, two points on the line that best fits the data in 586.diff
586.theory, points on the curve I = I0(eα-1(V -V min) - 1) versus V that best fits the data in
586.raw.
and so forth. Do this for all sevel LEDs, and the script below will create all 21 graphs in one
shot.
#!/bin/bash
for file in $(ls *.raw) do base=$(basename $file .raw) # create all of the analyzed data files ./analysis $base #create all of the graphs graph -T ps $base.theory -L "$base (raw data), best fit curve" -m 0 -S 4 -X "V (Volts)" -Y"I (mA)" $file > $base.1.ps graph -T ps $base.log.line -L "ln(I/I\sb0\eb+1) versus V for $base" -m 0 -S 4 -X "V (Volts)" -Y "ln(I/I\sb0\eb+1)" $base.line > $base.2.ps graph -T ps $base.diff.line -L "dI/dV versus I for $base" -m 0 -S 4 -X "I (mA)" -Y "dI/dV, (mA/V)" $base.diff > $base.3.ps done exit 0 |