[net.unix-wizards] question-- Bourne

arturo@humming.UUCP (Arturo Perez) (08/14/86)

Here's something I've wanted to do for a while but I can't seem to find the
way to do it.

In the csh you can do something like

ls foo
if (! $status) then
   echo "foo exists"
endif

The  key  thing  here  is  the  ability  to NOT the value of status. How is
this similar thing done in Bourne shell.

if ! ls foo
then
	echo foo does not exist
fi

In  summary,  how can I take the logical NOT of a command's return value in
the Bourne shell (which is God's gift to U**X :-)?
-- 
"Life is but a dream" - Lope de Vega
    "...for some and a NIGHTMARE for others!" Merlin, "Excalibur", the movie
Disclaimer?  What disclaimer?  I can back everything up with as much 
drivel as you like!

guy@sun.uucp (Guy Harris) (08/16/86)

> The  key  thing  here  is  the  ability  to NOT the value of status. How is
> this similar thing done in Bourne shell.
> 
> if ! ls foo
> then
> 	echo foo does not exist
> fi

Try

	if ls foo
	then
		:
	else
		echo foo does not exist
	fi

The ":"  is the pseudo-comment from old Bourne shells; it's really a command
that does nothing.

Not the cleanest syntax, but that's life.  (However, I'd rather have a shell
that requires that crud, but allows you to redirect the output of a "for"
loop, than one that permits you to negate exit status directly but won't let
you redirect the output of loops!  At least with the Bourne shell you can
get around the inability to negate exit status fairly easily.)

However, you may be better off doing

	if test ! -f foo

or something like that; unfortunately, "test" doesn't have a predicate for
"just test whether it exists", but you may really want a more restrictive
predicate anyway.
-- 
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com (or guy@sun.arpa)

dce@mips.UUCP (David Elliott) (08/16/86)

In article <150@humming.UUCP> arturo@humming.UUCP (Arturo Perez) writes:
>Here's something I've wanted to do for a while but I can't seem to find the
>way to do it.
>
>In the csh you can do something like
>
>ls foo
>if (! $status) then
>   echo "foo exists"
>endif
>
>The  key  thing  here  is  the  ability  to NOT the value of status. How is
>this similar thing done in Bourne shell.
>

Wrong. The key thing here is the ability to evaluate an expression. Though
not built in to most versions of sh, the 'test' command can be used for a
similar effect, as can 'expr', and you can always use 'case'.

Here are three ways:

1. The 'test' command (this also exists as '[' in many systems, so I'll use
   that here)

	ls foo
	if [ $? -eq 0 ]
	then
		echo "exists"
	fi

2. The 'expr' command (since this prints the boolean truth value, we throw
   the output away)

	ls foo
	if expr $? != 0 >/dev/null
	then
		echo "exists"
	fi

3. The 'case' statement

	ls foo
	case "$?" in
		0)
			echo "exists"
			;;
	esac

There are two problems with this:

	1. You have programmed-in knowledge that '0' is 'true' (this isn't
	   really so bad).
	2. If 'foo' doesn't exist, 'ls' may still exit with a 0. A quick look
	   at the 4.3BSD code proves me out.

What is really needed here is what Guy Harris suggested, which is:

	if [ -f foo ]
	then
		echo "exists"
	fi

except that '[ -f foo ]' only returns true if 'foo' is a regular file.

This brings up a couple of really strange (but valid) examples:

	case `echo foo*` in
		"foo" | "foo "*)
			echo "exists"
			;;
	esac


	# 'dummy' ensures proper 'for' syntax
	for i in foo* dummy
	{
		case "$i" in
			"foo")
				echo "exists"
				break
				;;
		esac
	}

(Excuse the prodigious use of quotes. I'm a "fanatic".)

			David Elliott
			{ucbvax,decvax,ihnp4}!decwrl!mips!dce

levy@ttrdc.UUCP (Daniel R. Levy) (08/17/86)

In article <150@humming.UUCP>, arturo@humming.UUCP (Arturo Perez) writes:
>In the csh you can do something like
>
>ls foo
>if (! $status) then
>   echo "foo exists"
>endif
>
>The  key  thing  here  is  the  ability  to NOT the value of status. How is
>this similar thing done in Bourne shell.
>
>if ! ls foo
>then
>	echo foo does not exist
>fi

To follow your example literally:

ls foo
if test $? -ne 0	# or, "if [ $? -ne 0 ]" is supported by modern /bin/sh's
then
	echo foo does not exist
fi

Of course, there are other ways to check for nonexistence of foo, e.g.:

if [ ! -f foo -a ! -d foo -a ! -p foo -a ! -c foo -a ! -b foo ]

# foo is not a file, a directory, a pipe, a character special device, or a
# block special device

which though "wordier" does not require the spawning of another process
presuming that "test" is a builtin in your shell.
-- 
 -------------------------------    Disclaimer:  The views contained herein are
|       dan levy | yvel nad      |  my own and are not at all those of my em-
|         an engihacker @        |  ployer or the administrator of any computer
| at&t computer systems division |  upon which I may hack.
|        skokie, illinois        |
 --------------------------------   Path: ..!{akgua,homxb,ihnp4,ltuxa,mvuxa,
	   go for it!  			allegra,ulysses,vax135}!ttrdc!levy

chris@pixutl.UUCP (chris) (08/18/86)

You can also do:

	( ls foo ) || echo not there

or, more cheaply:

	{ ls foo ; } || echo not there

and if you didn't want to see the output of the ls command,

	{ ls foo >/dev/null 2>&1 ; } || echo not there



Chris
-- 

 Chris Bertin       :  (603) 881-8791 x218
 xePIX Inc.         :
 51 Lake St         :  {allegra|ihnp4|cbosgd|ima|genrad|amd|harvard}\
 Nashua, NH 03060   :     !wjh12!pixel!pixutl!chris

anw@nott-cs.UUCP (08/20/86)

In article <6228@sun.uucp> guy@sun.uucp (Guy Harris) writes:
>Try
>
>	if ls foo
>	then
>		:
>	else
>		echo foo does not exist
>	fi

Or you could try

	ls foo ||
	    echo foo does not exist

In complicated situations, "if ... then ... else ... fi" is clearer, but
where there is only one subsidiary command I think "&&" and "||" can tidy
up shell scripts quite a lot.  I often use (V7 with SV shell) something like

	[ -w foo ] || fault "can't write to foo"

where "fault" is a suitable function, such as

	fault () { echo $0: error, "$@" 1>&2; exit 1; }

						-- Andy Walker,
						     Maths Dept, Nottm Univ

swa@COMET.LCS.MIT.EDU (Steven Augart) (08/21/86)

   From: Arturo Perez <arturo%humming.uucp@BRL.ARPA>
   Date: 14 Aug 86 14:12:45 GMT

   In the csh you can do something like

   ls foo
   if (! $status) then
      echo "foo exists"
   endif

(parenthetical note: "ls" will return status 0 whether or not it can
find foo.  The example is faulty).

   The  key  thing  here  is  the  ability  to NOT the value of status. How is
   this similar thing done in Bourne shell.

Can't be done directly in the Bourne shell, since the Bourne shell
simply doesn't have C-shell style expressions; they are handled
separately by the "test" and "expr" programs.  Since the bourne shell
doesn't have expressions, it also doesn't have an internal NOT
operator.

However, you can do this simple workaround (or you could if "ls foo"
returned 0 status to indicate that it found "foo" and nonzero status
to indicate that it hadn't found "foo"):

    if ls foo
    then
	    ;
    else
	    echo "foo not found"
    endif


Steven Augart
MIT Laboratory for Computer Science
swa@xx.lcs.mit.edu, swa@xx.ARPA

ignatz@aicchi.UUCP (Ihnat) (08/22/86)

There may be more elegant ways--it's sometimes tough to be elegant at 2:50
AM--but certainly, for filename FILE

	ls FILE >/dev/null 2>/dev/null

	if [ ! $? ]
	then
		<whatever negated thingies you want>
	fi;

works.  (As we all know, $? is the return code from the last executed command.)
However, if just testing existence, how about

	if [ -f FILE ]
	then
		<etc>
	fi;

Look at test(1); it's got a lot of nifty cases you can test...
-- 
	Dave Ihnat
	Analysts International Corporation
	(312) 882-4673
	ihnp4!aicchi!ignatz || ihnp4!homebru!ignatz

hahn@ames-prandtl.arpa (Jonathan Hahn) (08/23/86)

In article <150@humming.UUCP>, arturo@humming.UUCP (Arturo Perez) writes:
>In the csh you can do something like
>
>ls foo
>if (! $status) then
>   echo "foo exists"
>endif
>
>The  key  thing  here  is  the  ability  to NOT the value of status. How is
>this similar thing done in Bourne shell.
>
>if ! ls foo
>then
>	echo foo does not exist
>fi

I haven't seen any mention of our Bourne shell friend "||".  How about
(assuming ls returns correct status):

	ls foo || echo foo does not exist

If you want to get rid of the output and error messages from ls:

	ls foo > /dev/null 2>&1 || echo foo does not exist

And if you want a complex second statement:

	ls foo || {
		echo foo does not exist
		exit
	}

-jonathan hahn
NAS Program, Ames Research Center
Moffett Field, CA
hahn@ames-nas

ado@elsie.UUCP (Arthur David Olson) (08/24/86)

> I haven't seen any mention of our Bourne shell friend "||".  How about
> (assuming ls returns correct status):
> 
> 	ls foo || echo foo does not exist

For the truly esoterically minded
(especially those who don't want to run "ls" or "test" or any other
non-built-ins on BSD systems):

	case fo[o] in
		foo)	;;
		*)	echo foo does not exist ;;
		:-)	;;
	esac
--
UNIX is an AT&T Bell Laboratories trademark (or an AT&T registered trademark).
--
	UUCP: ..decvax!seismo!elsie!ado   ARPA: elsie!ado@seismo.ARPA
	DEC, VAX, Elsie & Ado are Digital, Borden & Ampex trademarks.

david@ukme.UUCP (David Herron, NPR Lover) (09/01/86)

In article <3220@brl-smoke.ARPA> swa@COMET.LCS.MIT.EDU (Steven Augart) writes:
>    if ls foo
>    then
>            ;
>    else
>            echo "foo not found"
>    endif

Or:

	#! /bin/sh
	# not.sh -- Logical NOT of the return status of a command
	#
	# USAGE: not command
	#
	if $@; then
		exit 1
	else
		exit 0
	fi

Allowing one to say:

	if not rsh e /bin/true; then
		echo ^G^Ge is down^G^G
	fi
-- 
David Herron,  cbosgd!ukma!david, david@UKMA.BITNET, david@ms.uky.csnet
	(I'm also "postmaster" at all those addresses)
	(And "news" and "netnews" and "uucp" and ....)

sja@ih1ap.UUCP (Steve Alesch) (09/12/86)

In article <6228@sun.uucp>, guy@sun.uucp (Guy Harris) writes:
> > The  key  thing  here  is  the  ability  to NOT the value of status. How is
> > this similar thing done in Bourne shell.
> > 
> > if ! ls foo
> > then
> > 	echo foo does not exist
> > fi
> 
> Try
> 
> 	if ls foo
> 	then
> 		:
> 	else
> 		echo foo does not exist
> 	fi
> 
> The ":"  is the pseudo-comment from old Bourne shells; it's really a command
> that does nothing.
> 
> Not the cleanest syntax, but that's life.  (However, I'd rather have a shell
> that requires that crud, but allows you to redirect the output of a "for"
> loop, than one that permits you to negate exit status directly but won't let
> you redirect the output of loops!  At least with the Bourne shell you can
> get around the inability to negate exit status fairly easily.)
> 
> However, you may be better off doing
> 
> 	if test ! -f foo
> 
> or something like that; unfortunately, "test" doesn't have a predicate for
> "just test whether it exists", but you may really want a more restrictive
> predicate anyway.

Correct me if I'm missing something.  What's wrong with:

	ls foo
	if [ $? != 0 ]; then
		echo foo does not exist
	fi
-- 

Steve Alesch	AT&T
(312)510-7881, ...!ihnp4!ih1ap!sja

chris@pixutl.UUCP (chris) (09/16/86)

> 
> Correct me if I'm missing something.  What's wrong with:
> 
> 	ls foo
> 	if [ $? != 0 ]; then
> 		echo foo does not exist
> 	fi
> -- 
> 
> Steve Alesch	AT&T
> (312)510-7881, ...!ihnp4!ih1ap!sja


It should be:

	if [ $? -ne 0 ]; then

  '!=' is used to compare strings, -ne and family, integers...  :-)


  Chris
-- 

 Chris Bertin       :  (603) 881-8791 x218
 xePIX Inc.         :
 51 Lake St         :  {allegra|ihnp4|cbosgd|ima|genrad|amd|harvard}\
 Nashua, NH 03060   :     !wjh12!pixel!pixutl!chris

dianeh@ism780c.UUCP (Diane Holt) (09/17/86)

In article <574@ih1ap.UUCP> sja@ih1ap.UUCP (Steve Alesch) writes:
>In article <6228@sun.uucp>, guy@sun.uucp (Guy Harris) writes:
>> > The  key  thing  here  is  the  ability  to NOT the value of status.
>> > How is this similar thing done in Bourne shell.
>> > if ! ls foo
>> > then
>> > 	echo foo does not exist
>> > fi
>> 
>> Try
>> 	if ls foo
>> 	then
>> 		:
>> 	else
>> 		echo foo does not exist
>> 	fi
>> [or]
>> 	if test ! -f foo
>> 
>Correct me if I'm missing something.  What's wrong with:
>	ls foo
>	if [ $? != 0 ]; then
>		echo foo does not exist
>	fi

I didn't see the original posting, so I'm not sure exactly what's trying to
be done, but my suggestion would be:

	ls foo || echo "foo does not exist"

The || is "OR" -- return "true" from the first command "OR" execute the
next one. Double ampersand (&&) is used to check the return from the first
command "AND" execute the next one. There is no limit on how many "next"
commands there can be or any restrictions on combinations of "OR"s and
"AND"s. I use this all the time.

P.S.
Obviously, this whole example is pretty silly, since 'ls' will output
"foo not found", if it doesn't really exist, so echoing that it doesn't is
superfluous...but I'm assuming that the command used is just an example and
not significant to the original poster's question...if it really *is*
significant, then you'd want to redirect the output: ls foo >/dev/null 2>&1...

Diane Holt
Interactive Systems Corp.
Santa Monica, CA
{seismo,decvax,cbosgd}!hplabs!sdcrdcf!ism780c!dianeh

"But I don't know anything about computers."
"Nobody does...but don't you want one for when you do find out?"

guy@sun.uucp (Guy Harris) (09/17/86)

> Correct me if I'm missing something.  What's wrong with:
> 
> 	ls foo
> 	if [ $? != 0 ]; then
> 		echo foo does not exist
> 	fi

It doesn't indicate quite as clearly as the other version that the
failure/success of "ls" is being tested.  It merely indicates that the exit
status of "ls" is being compared against 0; you have to associate this with
failure/success.  (See past discussions in net.lang.c about why Boolean
types exist even if you language happens to implement them as integral
types.)

In addition, 1) "ls" does not always return an exit status indicating
whether it could find the files in question or not and 2) "ls" *does* always
print the name of the file, if it finds it, or an error, if it doesn't.  If
"test" had a "does this file exist" predicate, then as I mentioned that
would be what you should use.
-- 
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com (or guy@sun.arpa)

lilly@leadsv.UUCP (Harriette Lilly) (09/27/86)

        Speaking of C shells.....

        I am just getting into some deep shell programming and have exausted
        (I think ) the resources here....

        I would like to find someone (or more than one) that I could
        exchange E-mail with about shells and possibly get some answers
        to some problems I am having.


        Any help in this area would be greatly appreciated.

        Thanx in advance....
						Harriette
						@ Lockheed for
						Telos Consulting

lilly@leadsv.UUCP (Harriette Lilly) (09/29/86)

           Thanks to those who answered, I will be writting you soon
           as if figure out how :-)

           P.S. I already have the UNIX C SHELL Field Guide, But even it
                it not answering all my questions.