Hi, everyone! First post here. I just assembled my first Linux computer and I'm trying to teach myself shell scripting. (Xubuntu and bash, respectively, but I'm not tied to either.)
I'm writing a program to deal with different kinds of files (to be executed from a text editor -- LaTeX'ing a .tex, compiling a .c or .cpp, etc.). This is partially because I want to have those functions, but also as a learning exercise.
To avoid redundancy I'd like to collect the handling for each type of file together, regardless of how I determined its type (by extension, header, or some other method). In a Windows batch file I'd use GOTO:
IF "%1"=="help" GOTO Help
. . .
:Help
. . .
GOTO end
. . .
:end
but it looks like there's no goto in bash.* At first it seemed simple: shell scripts support functions, so just make a function for each:
function Help {
. . .
}
. . .
if [ "$1" = "help" ]; then
Help
. . .
but functions capture whatever I echo.
If I wanted to implement this with functions, how can I get around the capturing? I'd guess that one of the redirection commands would work -- but I've had no luck so far. (It's only my first day, be gentle with me here!)
Subjectively, what's the 'right' or 'best' way to do what I want? Functions seem somewhat heavyweight when in many cases I'll just want to do a single line.
A function that includes echoes should still echo to the terminal.
Yes for one liners functions are no normally used, for your example a case statement might be more elegant, e.g.:
case "$1" in
"help")
echo "This is how you use this script, valid options are help and doit."
;;
"doit")
echo "Do your stuff here"
;;
*)
echo "You did not supply a valid option, try: $0 help."
exit 99
;;
esac
If you wanted to display the help info from "help" and * then that would benefit from a function.
I experimented around a bit. They do echo to stdout if they don't have an exit value:
function foo {
echo -n hi
# Uncomment this line to change the output from "hi again hi " to "again ".
#exit 0
}
foo
echo again
foo
but then I can't use them to pass along success/failure information. Right now the relevant part of the script would be something like this (short version, in function form):
recognized=1;
exec_c () {
gcc -O3 "$file" -o"$tfile"
}
exec_png () {
gpicview "$file"
}
cleanup () {
echo All done!
}
case "$full_ext" in
"gp.c")
gp2c-run "$file"
;; *)
recognized=0
esac
exit_status=$?
if [ recognized -eq 1 ]; then
cleanup
exit $exit_status
fi
recognized=1
case "$ext" in
"c" | "cpp")
exec_c
;; "png")
exec_png
;; *)
recognized=0
;;
esac
exit_status=$?
if [ recognized -eq 1 ]; then
cleanup
exit $exit_status
else
head4=`head -c4 "$file"`
png=`echo -e '\0211PNG'`
if [ "$head4" = "$png" ]; then
exec_png
fi
fi
Functions will echo as long as there is some command inside them which writes to stdout. If you want to suppress that, you can redirect output to /dev/null. It has nothing to do with exit code.
You can use "return <exit_code>" to pass around success/failure information. Using "exit <exit_code>" will quit the script altogether. Once you return, you can check $? to check for success/failure.
I don't want to suppress output, I want to show it.
I'll try that, thanks. But as you can see (try my example), exit does not exit the script, just the function. (I'm learning by doing; I never would have guessed that it would work that way.)
$ cat foo
#!/usr/bin/bash
function foo {
echo -n hi
# Uncomment this line to change the output from "hi again hi " to "again ".
exit 0
}
foo
echo again
foo
$
$ foo
hi$
$
OK, I have a working version now. It's not very polished but hey -- it's my first script! It took me about three hours, but there was a lot of reading in that time.
Hmm, you're right. I had a different version (more complicated) that worked as I described, but I deleted that an hour ago as I found better ways to do things. But I'm not crazy -- I did test whether the script was exiting or not.
I'll chalk that up to 'bizarre things happen some times' or something.