5

Example:

#!/bin/sh

a() {
R=f
ls -1 a*
[ "$?" == "1" ] && { R=t; }
echo $R
}

r=`a`
echo $r

$r contains t or f but also the output of the ls command.

I may write ls -1 a* >/dev/null 2>/dev/null, but if there is a more complex script that can be lead to errors.

Is there any way to return a single value from a() ?

Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
PeterMmm
  • 24,152
  • 13
  • 73
  • 111

4 Answers4

4

A shell function can return a numeric value. Consider 0 and 1 rather than 'f' and 't'

#!/bin/sh

a() {
R=0
ls -1 a*
[ "$?" == "1" ] && { R=1; }
return $R
}

a
r=$?
echo $r

This will still write output from the ls -1 a* which you probably still want to dispose of, but the value of r will be either 0 or 1 and won't include the output.

The other examples of redirecting output either from a line or a whole block are good, and, as others suggested, you should get to know other ways to test for conditions (but I was assuming the ls was kind of an arbitrary example)

Stephen P
  • 14,422
  • 2
  • 43
  • 67
  • Why not skip the whole funky business with `$R` and just run the `ls` and then `return $?`? – Caleb Jul 31 '13 at 08:44
  • @Caleb - this answer is a modification to PeterMmm's original script to demonstrate how a shell function can return a value. I'm sure this whole sample function could be dispensed with, but I don't know what he might be doing in his real code. – Stephen P Jul 31 '13 at 23:54
1

you don't have to use ls to check for files starting with a. Just use the shell

a() {
  shopt -s nullglob
  ret="f"
  for file in a*
  do   
    ret="t"
    break
  done
  echo "$ret"
}
ghostdog74
  • 327,991
  • 56
  • 259
  • 343
  • This is an example, not my question. How can i avoid to write everywhere ">/dev/null 2>/dev/null" when i want to have a single value/string from a script function. – PeterMmm Jun 29 '10 at 12:01
1

You can put a redirection on a list of commands:

{
  command1
  command2
} >/dev/null

If at some point in the script you don't want any output from subsequent commands, you can redirect the shell's output with the exec builtin:

echo interesting
exec >/dev/null
echo boring

Note that this lasts until the end of the script, not just until the end of a function. This takes care of commands after the interesting one but not before.

There is a way to revert the effect of exec /dev/null, by using file descriptor manipulations. I don't necessarily recommend it though, because it can be tricky to work out in practice. The idea is to relocate whatever is connected to the standard output to a different descriptor, then redirect standard output to a different file, and finally relocate the original standard output back to standard output.

{
  exec 3>&1         # duplicate fd 3 to fd 1 (standard output)
  exec >/dev/null   # connect standard output to /dev/null
  echo boring
  exec 1>&3         # connect standard output back to what was saved in fd 3
  echo interesting
  exec >/dev/null   # connect standard output to /dev/null again
  echo more boring
} 3>/dev/null       # The braced list must have its fd 3 connected somewhere,
                    # even though nothing will actually be written to it.
Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
0
a() { 
ls -1 a*  > /dev/null
[ "$?" == "0" ] && echo t  || echo f

} 

r=`a` 
echo $r 

Consider using [ -f filename ] and other file tests as well.

jim mcnamara
  • 16,005
  • 2
  • 34
  • 51