0

What is the correct way to output an exit status in bash? As far as I know, the exit status called by $? corresponds to the status of the last command executed.

The script being worked on has a few conditional checks on the files fed as arguments, for example, a check on whether any files were named at all or if a file exists or not.

So I have conditional statements like this:

if [ $# -eq 0 ] ; then
     echo "No file name(s) given! \nExit status=$?"
     exit

if [ ! -e "$fName" ] ; then
     echo "$fName does not exist! \nExit status=$?"
     exit 

But these return an exit status of 0. I'm not entirely sure even what exit codes would be appropriate for each of these situations, but I think both 1 would work for both based on this. Should I just hard-code the 1 into the conditional statement or change the logic so unix outputs an error code? Also, what command would the 0 that I get for the above example be the exit code for?

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
Conner M.
  • 1,954
  • 3
  • 19
  • 29
  • BTW, `echo` too has an exit status, so by the time you get to the `exit`, your last exit status is that of the `echo`, so (presuming that the `echo` successfully wrote its output) `exit`'s default behavior of `exit "$?"` will have the effect of `exit 0`, no matter what `$?` had been before `echo` ran. – Charles Duffy Jun 27 '18 at 02:51
  • 1
    As another aside -- I strongly, **strongly** recommend avoiding the ABS as a reference; when it's not outright wrong, it has a long history of showing bad practices in its examples. The [bash-hackers' wiki](http://wiki.bash-hackers.org/) and the [BashGuide](http://mywiki.wooledge.org/BashGuide) are far better sources, as of course is the [official manual](https://www.gnu.org/software/bash/manual/bash.html). – Charles Duffy Jun 27 '18 at 02:57
  • Besides the link, was there something in the code that looked like bad practice? – Conner M. Jun 27 '18 at 03:01
  • I was responding to the link, but using `echo` with backslash literals is unspecified by POSIX and has behavior that various across shells (or even across runtime configurations, such as varying on the state of the `xpg_echo` flag in bash); see the APPLICATION USAGE section of http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html – Charles Duffy Jun 27 '18 at 03:06
  • BTW, personally, I might write these checks more like `(( $# )) || { echo "ERROR: No file names given!" >&2; exit 1; }` (if we're using bashisms; `[ "$#" -eq 0 ] && { ...` otherwise) and `[[ -e $fName ]] || { echo "ERROR: Could not find $fName" >&2; exit 1; }` (here, using `[[` rather than `[` to get extended syntax making quotes unnecessary; again, an extension, but an explicit one that behaves consistently across ksh-inspired shells -- bash and zsh among them -- where it's available). – Charles Duffy Jun 27 '18 at 03:10
  • I'm using Putty and the `{ }s` in `... || { echo ...; exit 1;}` aren't recognized. When I remove them bash picks up the exit and leaves the script. Do you know where I can learn more about this type of syntax? – Conner M. Jun 27 '18 at 14:33
  • It's completely standard POSIX-compliant shell syntax -- your terminal program (PuTTY or otherwise) doesn't change how the shell parses the commands you run. Can you come up with a reproducer someone else can use to see the syntax error ourselves? (As a self-contained, copy-and-pastable reproducer: `bash -c 'false || { echo "failed"; exit 1; }'` should emit `failed` and exit, whereas `bash -c 'true || { echo "failed"; exit 1; }; echo "succeeded"'` should successfully emit `succeeded` when the above are copied-and-pasted). – Charles Duffy Jun 27 '18 at 15:33
  • ...do note that much of the syntax is sensitive to whitespace here -- leaving it out (or leaving out the trailing `;`s when not replacing them with newlines) can cause trouble. – Charles Duffy Jun 27 '18 at 15:36
  • I start to get expected end of script errors – Conner M. Jun 27 '18 at 15:38
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/173900/discussion-between-charles-duffy-and-conner-m). – Charles Duffy Jun 27 '18 at 15:41
  • See also [Why is testing “$?” to see if a command succeeded or not, an anti-pattern?](https://stackoverflow.com/questions/36313216/why-is-testing-to-see-if-a-command-succeeded-or-not-an-anti-pattern) – tripleee Feb 01 '21 at 06:16

1 Answers1

3

In both of these cases, the last command executed was [, which exited with 0 status ("success") to land you in the "true" block.

Yes, you need to specify a non-zero exit code for the exit command.

Pedantically "unix" does not output the error code: it's the shell running your script that exits with the specified status.

glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • 2
    Yes, it's a command, not mere syntax. It's also known as `test`. At an interactive bash prompt, enter `help [` for the details. – glenn jackman Jun 27 '18 at 02:15
  • I'd suggest starting with `type -a [`, which will provide enough information to know whether `help` (for shell builtins or keywords) or `man` (for external commands) is the next step. (Several commands are *both* shell builtins and external commands; the shell version is in such cases effectively a performance optimization). – Charles Duffy Jun 27 '18 at 02:52
  • Note that `[[ ]]` and `(( ))` *are* shell syntax (in bash and some other shells), but still affect `$?` as though they were commands. – Gordon Davisson Jun 27 '18 at 03:36