What's the Meaning of a ! Before a Command in the Shell

What's the meaning of a ! before a command in the shell?

TL;DR: This is just by-passing the set -e flag in the specific line where you are using it.


Adding add to hek2mgl's correct and useful answer.

You have:

set -e
! command

Bash Reference Manual → Pipelines describes:

Each command in a pipeline is executed in its own subshell. The exit status of a pipeline is the exit status of the last command in the pipeline (...). If the reserved word ‘!’ precedes the pipeline, the exit status is the logical negation of the exit status as described above. The shell waits for all commands in the pipeline to terminate before returning a value.

This means that ! preceding a command is negating the exit status of it:

$ echo 23
23
$ echo $?
0
# But
$ ! echo 23
23
$ echo $?
1

Or:

$ echo 23 && echo "true" || echo "fail"
23
true
$ ! echo 23 && echo "true" || echo "fail"
23
fail

The exit status is useful in many ways. In your script, used together with set -e makes the script exit whenever a command returns a non-zero status.

Thus, when you have:

set -e
command1
command2

If command1 returns a non-zero status, the script will finish and won't proceed to command2.

However, there is also an interesting point to mention, described in 4.3.1 The Set Builtin:

-e

Exit immediately if a pipeline (see Pipelines), which may consist of a single simple command (see Simple Commands), a list (see Lists), or a compound command (see Compound Commands) returns a non-zero status. The shell does not exit if the command that fails is part of the command list immediately following a while or until keyword, part of the test in an if statement, part of any command executed in a && or || list except the command following the final && or ||, any command in a pipeline but the last, or if the command’s return status is being inverted with !. If a compound command other than a subshell returns a non-zero status because a command failed while -e was being ignored, the shell does not exit. A trap on ERR, if set, is executed before the shell exits.


Taking all of these into consideration, when you have:

set -e
! command1
command2

What you are doing is to by-pass the set -e flag in the command1. Why?

  • if command1 runs properly, it will return a zero status. ! will negate it, but set -e won't trigger an exit by the because it comes from a return status inverted with !, as described above.
  • if command1 fails, it will return a non-zero status. ! will negate it, so the line will end up returning a zero status and the script will continue normally.

What is meaning of '#' before a variable in shell script?

In this context, it stands for the the length of the value of that variable:

$ v="hello"
$ echo ${#v}
5

$ v="bye"
$ echo ${#v}
3

So what does this command?

END_POS=$((${#column}-$COLON_INDEX))

It gets the length of the value in $column and substracts the value in $COLON_INDEX using the $(( )) syntax to perform arithmetic operations:

$ column="hello"
$ colon_index=2
$ r=$((${#column}-$colon_index)) # len("hello") - 2 = 5 - 2
$ echo $r
3

From Arithmetic expression:

(( )) without the leading $ is not a standard sh feature. It comes
from ksh and is only available in ksh, Bash and zsh. $(( ))
substitution is allowed in the POSIX shell. As one would expect, the
result of the arithmetic expression inside the $(( )) is substituted
into the original command. Like for parameter substitution, arithmetic
substitution is subject to word splitting so should be quoted to
prevent it when in list contexts.

In bash what does ! (exclamation mark) before command means?

In bash, if you type ! followed by a command name, it will substitute it with the last command in your history starting by that name.

So in your case !git was substituted with git clone somerepo so the whole line was translated to git clone somerepo status

What is the $ before shell command

It's pretty much just there as a separator between the prompt and what you actually type. It's like the > in a Windows/DOS prompt. It indicates a normal user privileges. If the shell had superuser privileges, there would be a # instead of a $.

Hope this helps!

what means $ (ampersand) in a command?

In Bash the '$' sign means that a normal user logged into the system can execute a command. If you're logged in as the root user, the prompt is '#' (hash or number symbol).

For further reading about the use and history of the prompt, please have a look at https://superuser.com/questions/57575/what-is-the-origin-of-the-unix-dollar-prompt

What does it mean in shell when we put a command inside dollar sign and parentheses: $(command)

Usage of the $ like ${HOME} gives the value of HOME. Usage of the $ like $(echo foo) means run whatever is inside the parentheses in a subshell and return that as the value. In my example, you would get foo since echo will write foo to standard out

What does & at the end of a linux command mean?

The & makes the command run in the background.

From man bash:

If a command is terminated by the control operator &, the shell
executes the command in the background in a subshell. The shell does
not wait for the command to finish, and
the return status is 0.

what is the meaning of FOOBAR=foobar followed by a shell command?

It sets that environment variable to that value only for that process.

Here, step by step, is what happens:

  • Original command: FOOBAR=1 echo $FOOBAR
  • Shell performs substitution: command is now FOOBAR=1 echo
  • Shell fork(2)s a new process
  • Environment variable is created in the new process: command is now echo (with $FOOBAR equal to 1)
  • New process is exec(3)ed: \n is output
  • New process exits and is reaped by the shell

At no point does the parent process see the assigned value of $FOOBAR.



Related Topics



Leave a reply



Submit