Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

compound command

40 views
Skip to first unread message

Bit Twister

unread,
Jan 31, 2023, 12:12:24 AM1/31/23
to
Downloaded ShellCheck-0.9.0-1.2.x86_64.rpm
ran

# shellcheck -x 00_common_changes

In 00_common_changes line 29:
cd /etc/rsyslog.d
^---------------^ SC2164 (warning): Use 'cd ... || exit' or 'cd ... || return' in case cd fails.

Did you mean:
cd /etc/rsyslog.d || exit


What came to mind that the script would exit without telling me why.

So I changed it to
cd /etc/rsyslog.d || echo "cd /etc/rsyslog.d failed" ; exit
script exits, guess because of ; exit

So I thought braces would solve my problem but I get
cd /etc/rsyslog.d || { echo "cd /etc/rsyslog.d failed" ; exit}
>
which indicates it is waiting for more input and I can not see why.

Any suggestions for cleaning up the problem.

Other option is do a
if [ $? -ne 0 ] ; then
echo "cd /etc/rsyslog.d failed"
exit
fi.

$ bash --version
bash --version
GNU bash, version 5.2.15(1)-release (x86_64-mageia-linux-gnu)


Keith Thompson

unread,
Jan 31, 2023, 12:21:26 AM1/31/23
to
Bit Twister <BitTw...@mouse-potato.com> writes:
[...]
> So I thought braces would solve my problem but I get
> cd /etc/rsyslog.d || { echo "cd /etc/rsyslog.d failed" ; exit}
[...]

It's parsing `exit}` as a single command name (and if you added a space
it would treat `}` as an argument to `exit`). Add a semicolon after
"exit".

cd /etc/rsyslog.d || { echo "cd /etc/rsyslog.d failed"; exit; }

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
Working, but not speaking, for XCOM Labs
void Void(void) { Void(); } /* The recursive call of the void */

Janis Papanagnou

unread,
Jan 31, 2023, 12:25:25 AM1/31/23
to
On 31.01.2023 06:12, Bit Twister wrote:
> Downloaded ShellCheck-0.9.0-1.2.x86_64.rpm
> ran
>
> # shellcheck -x 00_common_changes
>
> In 00_common_changes line 29:
> cd /etc/rsyslog.d
> ^---------------^ SC2164 (warning): Use 'cd ... || exit' or 'cd ... || return' in case cd fails.
>
> Did you mean:
> cd /etc/rsyslog.d || exit
>
>
> What came to mind that the script would exit without telling me why.
>
> So I changed it to
> cd /etc/rsyslog.d || echo "cd /etc/rsyslog.d failed" ; exit
> script exits, guess because of ; exit
>
> So I thought braces would solve my problem but I get
> cd /etc/rsyslog.d || { echo "cd /etc/rsyslog.d failed" ; exit}

Does this work without error? - I'd have expected { ... ; exit ;}

>>
> which indicates it is waiting for more input and I can not see why.

exit}

is a non-existing command, and the opening { is thus not closed.

>
> Any suggestions for cleaning up the problem.

Besides above fix I usually provide a function to simplify the code
with an optional error code

cd some_dir || err_exit "some msg" 42

For warnings a '0' (or no) value may just print the message without
exiting.

Janis

Bit Twister

unread,
Jan 31, 2023, 1:57:15 AM1/31/23
to
On Mon, 30 Jan 2023 21:21:19 -0800, Keith Thompson wrote:
> Bit Twister <BitTw...@mouse-potato.com> writes:
> [...]
>> So I thought braces would solve my problem but I get
>> cd /etc/rsyslog.d || { echo "cd /etc/rsyslog.d failed" ; exit}
> [...]
>
> It's parsing `exit}` as a single command name (and if you added a space
> it would treat `}` as an argument to `exit`). Add a semicolon after
> "exit".
>
> cd /etc/rsyslog.d || { echo "cd /etc/rsyslog.d failed"; exit; }

that is the solution.

Bit Twister

unread,
Jan 31, 2023, 2:02:00 AM1/31/23
to
Yeah I had thought of the function. I am trying to get rid of the message
so I tried this, but not getting a line of code in the message.
$ t
/home/bittwister/local/work/t: line 12: cd: /aa/: No such file or directory
rtn code is 1
FAILED with 1

was trying the get the line of code before FAILED with 1

#!/bin/bash

function ucd ()
{ _rtn=$?
echo "rtn code is $_rtn "
_msg="${BASH_SOURCE[${BASH_LINENO[0]}]} "
echo "$_msg FAILED with $_rtn"
exit $_rtn
} # function ucd


cd /aa/ || ucd

exit

Janis Papanagnou

unread,
Jan 31, 2023, 2:27:45 AM1/31/23
to
On 31.01.2023 08:01, Bit Twister wrote:
> On Tue, 31 Jan 2023 06:25:20 +0100, Janis Papanagnou wrote:
>> On 31.01.2023 06:12, Bit Twister wrote:
>>> [...]
>>>
>>> So I thought braces would solve my problem but I get
>>> cd /etc/rsyslog.d || { echo "cd /etc/rsyslog.d failed" ; exit}
>>
>> Does this work without error? - I'd have expected { ... ; exit ;}
>>
>>>>
>>> which indicates it is waiting for more input and I can not see why.
>>
>> exit}
>>
>> is a non-existing command, and the opening { is thus not closed.
>>
>>>
>>> Any suggestions for cleaning up the problem.
>>
>> Besides above fix I usually provide a function to simplify the code
>> with an optional error code
>>
>> cd some_dir || err_exit "some msg" 42
>>
>> For warnings a '0' (or no) value may just print the message without
>> exiting.
>
> Yeah I had thought of the function. I am trying to get rid of the message
> so I tried this, but not getting a line of code in the message.

Well, my suggestion to use a function was meant to avoid more complex
braced expressions like the one I depicted as { echo "..." ; exit ;}
if you have error checks in many places.

Deviating from you original post you now want the source code line
number in the message as I understand...

> $ t
> /home/bittwister/local/work/t: line 12: cd: /aa/: No such file or directory
> rtn code is 1
> FAILED with 1
>
> was trying the get the line of code before FAILED with 1
>
> #!/bin/bash
>
> function ucd ()
> { _rtn=$?
> echo "rtn code is $_rtn "
> _msg="${BASH_SOURCE[${BASH_LINENO[0]}]} "

...but I cannot tell for bash; you'd have to inspect the man page for
these variables.

(In ksh I'd use _msg="${.sh.lineno} " here, but that doesn't help
you with bash. Sorry.)

Janis

Janis Papanagnou

unread,
Jan 31, 2023, 2:49:33 AM1/31/23
to
On 31.01.2023 08:01, Bit Twister wrote:
>> [...]
>
> Yeah I had thought of the function. I am trying to get rid of the message
> so I tried this, but not getting a line of code in the message.
> $ t
> /home/bittwister/local/work/t: line 12: cd: /aa/: No such file or directory
> rtn code is 1
> FAILED with 1
>
> was trying the get the line of code before FAILED with 1
>
> #!/bin/bash
>
> function ucd ()
> { _rtn=$?
> echo "rtn code is $_rtn "
> _msg="${BASH_SOURCE[${BASH_LINENO[0]}]} "

Did you want to print the source and the line number here, two
individual variables? - This would be

_msg="${BASH_SOURCE}[${BASH_LINENO[0]}] "

(In your code you used the line number as index to the source name.)

Janis

Ed Morton

unread,
Feb 3, 2023, 12:06:49 PM2/3/23
to
On 1/30/2023 11:21 PM, Keith Thompson wrote:
> Bit Twister <BitTw...@mouse-potato.com> writes:
> [...]
>> So I thought braces would solve my problem but I get
>> cd /etc/rsyslog.d || { echo "cd /etc/rsyslog.d failed" ; exit}
> [...]
>
> It's parsing `exit}` as a single command name (and if you added a space
> it would treat `}` as an argument to `exit`). Add a semicolon after
> "exit".
>
> cd /etc/rsyslog.d || { echo "cd /etc/rsyslog.d failed"; exit; }
>

I'd make it

cd /etc/rsyslog.d || { rc="$?"; echo "cd /etc/rsyslog.d failed with
result $rc" >&2; exit "$rc"; }

or similar so you have the exit status in the error message, the error
message goes to stderr instead of stdout, and you exit the script with a
failure rather than success exit status.

Ed.

lxvs

unread,
Feb 5, 2023, 8:19:35 PM2/5/23
to
On Tuesday, January 31, 2023 at 1:12:24 PM UTC+8, Bit Twister wrote:
> What came to mind that the script would exit without telling me why.
>
> So I changed it to
> cd /etc/rsyslog.d || echo "cd /etc/rsyslog.d failed" ; exit
> script exits, guess because of ; exit

cd will tell you why exited if failed, so `cd || exit' is fine.

Keith Thompson

unread,
Feb 5, 2023, 8:31:14 PM2/5/23
to
I'd suggest `cd /etc/rsyslog.d || exit 1`, so the script indicates that
it failed.

$ cat tmp.sh
#!/bin/sh

cd /no/such/directory || exit 1
$ ./tmp.sh
./tmp.sh: 3: cd: can't cd to /no/such/directory
$ ./tmp.sh && echo OK || echo FAILED
./tmp.sh: 3: cd: can't cd to /no/such/directory
FAILED
$

Zhao-hui Liu

unread,
Feb 5, 2023, 8:40:46 PM2/5/23
to
On Monday, February 6, 2023 at 9:31:14 AM UTC+8, Keith Thompson wrote:
> I'd suggest `cd /etc/rsyslog.d || exit 1`, so the script indicates that
> it failed.

`command || exit' is sufficient to indicate script failure, and better than `command || exit 1', because the latter always returns 1 if fails, while the former reflects the exit code of command.

Keith Thompson

unread,
Feb 5, 2023, 11:41:28 PM2/5/23
to
Good point.

I had forgotten that the built-in `exit` command with no arguments uses
the exit status of the last command executed. (POSIX specifies this.)

If you prefer to be more explicit (as I do), you can use `command || exit $?`.

(Anyone writing scripts in csh or tcsh for some reason should be aware
that, according to the respective man pages, csh's builtin `exit` with
no arguments exits with value of `$status`, but tcsh's `exit` exits with
a status of 0 -- and my quick experiment is not consistent with the man
pages.)

Janis Papanagnou

unread,
Feb 6, 2023, 1:34:28 AM2/6/23
to
On 06.02.2023 05:41, Keith Thompson wrote:
> Zhao-hui Liu <lll...@gmail.com> writes:
>> On Monday, February 6, 2023 at 9:31:14 AM UTC+8, Keith Thompson wrote:
>>> I'd suggest `cd /etc/rsyslog.d || exit 1`, so the script indicates that
>>> it failed.
>>
>> `command || exit' is sufficient to indicate script failure, and better
>> than `command || exit 1', because the latter always returns 1 if
>> fails, while the former reflects the exit code of command.
>
> Good point.
>
> I had forgotten that the built-in `exit` command with no arguments uses
> the exit status of the last command executed. (POSIX specifies this.)
>
> If you prefer to be more explicit (as I do), you can use `command || exit $?`.

Notwithstanding there's a point in explicitly specifying an exit code
(i.e. different from $?), depending on where you come from.

If you think your scripts from a systems perspective you may not be
interested in the technical reason that $? (or a plain exit) provides;
you may want to get information from the software process as a whole,
effectively a process oriented abstraction layer. And the concrete
command's $? would go into a log file for technical debugging where
it matters.

BTW; what error codes does 'cd' return besides "1"? - The most common
cases [for me] are non-existing directories, access permissions, and
file type mismatch, all of them indicated with exit code "1" [in my
environment] (and differentiated only by the textual output on stderr).

Janis

Keith Thompson

unread,
Feb 6, 2023, 4:15:28 AM2/6/23
to
Janis Papanagnou <janis_pap...@hotmail.com> writes:
> On 06.02.2023 05:41, Keith Thompson wrote:
>> Zhao-hui Liu <lll...@gmail.com> writes:
>>> On Monday, February 6, 2023 at 9:31:14 AM UTC+8, Keith Thompson wrote:
>>>> I'd suggest `cd /etc/rsyslog.d || exit 1`, so the script indicates that
>>>> it failed.
>>>
>>> `command || exit' is sufficient to indicate script failure, and better
>>> than `command || exit 1', because the latter always returns 1 if
>>> fails, while the former reflects the exit code of command.
>>
>> Good point.
>>
>> I had forgotten that the built-in `exit` command with no arguments uses
>> the exit status of the last command executed. (POSIX specifies this.)
>>
>> If you prefer to be more explicit (as I do), you can use `command || exit $?`.
>
> Notwithstanding there's a point in explicitly specifying an exit code
> (i.e. different from $?), depending on where you come from.
>
> If you think your scripts from a systems perspective you may not be
> interested in the technical reason that $? (or a plain exit) provides;
> you may want to get information from the software process as a whole,
> effectively a process oriented abstraction layer. And the concrete
> command's $? would go into a log file for technical debugging where
> it matters.

Agreed. If all I care about is that the script should die with a
failure status, `exit 1` is probably exactly what I want.

> BTW; what error codes does 'cd' return besides "1"? - The most common
> cases [for me] are non-existing directories, access permissions, and
> file type mismatch, all of them indicated with exit code "1" [in my
> environment] (and differentiated only by the textual output on stderr).

The bash documentation just says:

The return status is zero if the directory is successfully changed,
non-zero otherwise.

POSIX says ">0" if an error occurred.

In practice an error status other than 1 would be mildly surprising.
0 new messages