What Is the Use of $# in Bash

What is the use of $# in Bash

From Learn Bash in Y minutes:

# Builtin variables:
# There are some useful builtin variables, like
echo "Last program's return value: $?"
echo "Script's PID: $$"
echo "Number of arguments passed to script: $#"
echo "All arguments passed to script: $@"
echo "The script's name: $0"
echo "Script's arguments separated into different variables: $1 $2..."

What's the use of `!#` in bash?

As mentioned comments on the question and other answer(s), you can easily find the section of man bash:

!#     The entire command line typed so far.

What isn't made explicit by the man pages or other documentation and perhaps leading you your befuddlement to a useful use for !# is that bash event designators are meant to be used in combination with the word designators and modifiers (found just below event designators on the man page). The use cases also make more sense when chaining commands together with pipes, ; or &/&&

For example:

I could use the substitution modifier to run a script foo.sh against two inputs bar and baz:

$ ./foo.sh bar; !#:s/bar/baz/

expands to form:

./foo.sh bar; ./foo.sh baz;

Or an example from the Docs (R.I.P. Docs) reproduced below shows how to use the word selector :N to select the first argument to the command as typed so far and neatly cd into the just created directory:

$ mkdir backup_download_directory && cd !#:1
mkdir backup_download_directory && cd backup_download_directory

These examples are pretty trivial, but I hope they show how !# could really save somebody some serious redundant typing while crafting powerful one-liners.

Use of $- in shell script

It returns the current shell's flags. The $- variable contains the shell's flags currently active in your terminal. These flags determine how your shell will function for you. In your case, these flags have the following meaning (note that all of these are defaults):

  • h: Short for “hashall” (read that “hash all”), this tells bash to
    remember the locations of commands it has found through querying your
    PATH.

  • i: Short for “interactive”, which is good, because this is a shell
    with which I’m interacting (entering input & getting back output)!1

  • m: Short for “monitor”, this enables job control in bash (so you can
    send jobs to the background via bg, for instance).

  • B: Short for “braceexpand” (read as “brace expand”), this allows you
    to use the very efficient brace expansion in bash2.

  • H: Short for “histexpand” (read as “hist [history] expand”), this is
    what enables you to re-run a command from your history by prefacing
    its number with an exclamation point3.

These flags can be changed by using the set command. For example :

set +H 
echo $-
himB

remove the H flag. Whereas -

set -H
echo $-
himBH

restores it. That's it, a bit confusing but + removes a flag, whereas - adds a flag.


More info:

  • Bash man
  • Tutorial

Difference between ${} and $() in Bash

The syntax is token-level, so the meaning of the dollar sign depends on the token it's in. The expression $(command) is a modern synonym for `command` which stands for command substitution; it means run command and put its output here. So

echo "Today is $(date). A fine day."

will run the date command and include its output in the argument to echo. The parentheses are unrelated to the syntax for running a command in a subshell, although they have something in common (the command substitution also runs in a separate subshell).

By contrast, ${variable} is just a disambiguation mechanism, so you can say ${var}text when you mean the contents of the variable var, followed by text (as opposed to $vartext which means the contents of the variable vartext).

The while loop expects a single argument which should evaluate to true or false (or actually multiple, where the last one's truth value is examined -- thanks Jonathan Leffler for pointing this out); when it's false, the loop is no longer executed. The for loop iterates over a list of items and binds each to a loop variable in turn; the syntax you refer to is one (rather generalized) way to express a loop over a range of arithmetic values.

A for loop like that can be rephrased as a while loop. The expression

for ((init; check; step)); do
body
done

is equivalent to

init
while check; do
body
step
done

It makes sense to keep all the loop control in one place for legibility; but as you can see when it's expressed like this, the for loop does quite a bit more than the while loop.

Of course, this syntax is Bash-specific; classic Bourne shell only has

for variable in token1 token2 ...; do

(Somewhat more elegantly, you could avoid the echo in the first example as long as you are sure that your argument string doesn't contain any % format codes:

date +'Today is %c. A fine day.'

Avoiding a process where you can is an important consideration, even though it doesn't make a lot of difference in this isolated example.)

Why do you need to put #!/bin/bash at the beginning of a script file?

It's a convention so the *nix shell knows what kind of interpreter to run.

For example, older flavors of ATT defaulted to sh (the Bourne shell), while older versions of BSD defaulted to csh (the C shell).

Even today (where most systems run bash, the "Bourne Again Shell"), scripts can be in bash, python, perl, ruby, PHP, etc, etc. For example, you might see #!/bin/perl or #!/bin/perl5.

PS:
The exclamation mark (!) is affectionately called "bang". The shell comment symbol (#) is sometimes called "hash".

PPS:
Remember - under *nix, associating a suffix with a file type is merely a convention, not a "rule". An executable can be a binary program, any one of a million script types and other things as well. Hence the need for #!/bin/bash.

What is usage() in shell scripting?

It's a just a convention. When something is wrong with the values supplied on the command line, people often use a function called usage() to tell you the problem/the values expected. For example:

#!/bin/sh
if [ $# -ne 1 ] ; then
usage
else
filename=$1
fi
...

What is the use of bash -c command?

bash -c option with ssh is one such method to execute multi line commands on the ssh server with variable expansion.

Say you have

VAR1="Variable 1"
ssh app@HOSTNAME '
ls
pwd
if true; then
echo "True"
echo $VAR1 # <-- it won't work
else
echo "False"
fi
'

But with bash -c

VAR1="Variable 1"
ssh -t "${SSH_USER}@${SERVER_IP}" bash -c "'
ls
pwd
if true; then
echo $VAR1 <-- This works
else
echo "False"
fi
'"

What is the purpose of the : (colon) GNU Bash builtin?

Historically, Bourne shells didn't have true and false as built-in commands. true was instead simply aliased to :, and false to something like let 0.

: is slightly better than true for portability to ancient Bourne-derived shells. As a simple example, consider having neither the ! pipeline operator nor the || list operator (as was the case for some ancient Bourne shells). This leaves the else clause of the if statement as the only means for branching based on exit status:

if command; then :; else ...; fi

Since if requires a non-empty then clause and comments don't count as non-empty, : serves as a no-op.

Nowadays (that is: in a modern context) you can usually use either : or true. Both are specified by POSIX, and some find true easier to read. However there is one interesting difference: : is a so-called POSIX special built-in, whereas true is a regular built-in.

  • Special built-ins are required to be built into the shell; Regular built-ins are only "typically" built in, but it isn't strictly guaranteed. There usually shouldn't be a regular program named : with the function of true in PATH of most systems.

  • Probably the most crucial difference is that with special built-ins, any variable set by the built-in - even in the environment during simple command evaluation - persists after the command completes, as demonstrated here using ksh93:

    $ unset x; ( x=hi :; echo "$x" )
    hi
    $ ( x=hi true; echo "$x" )

    $

    Note that Zsh ignores this requirement, as does GNU Bash except when operating in POSIX compatibility mode, but all other major "POSIX sh derived" shells observe this including dash, ksh93, and mksh.

  • Another difference is that regular built-ins must be compatible with exec - demonstrated here using Bash:

    $ ( exec : )
    -bash: exec: :: not found
    $ ( exec true )
    $
  • POSIX also explicitly notes that : may be faster than true, though this is of course an implementation-specific detail.

Bash - what's the use of fi ;; ?

fi closes the if statement, while ;; closes the current entry in the case statement.



Related Topics



Leave a reply



Submit