Learning scripting -- functions capturing output

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.

  1. 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!)
  2. 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.
  • Yes, I'm familiar with Dijkstra's diatribe.

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.

HTH

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.)

There are no exit commands in the three functions in your example. You are running exit from main body.

First example, second comment. You're referring to my code snippet, I'm talking about my short testcase.

Short testcase:

$ 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. :eek: