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)!1m: 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 oftrue
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 thantrue
, 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
What Is the Linux Built-In Driver Load Order
Sub-Shell Differences Between Bash and Ksh
How to Setup and Clone a Remote Git Repo on Windows
How to Use Awk to Convert All the Lower-Case Letters into Upper-Case
D-Bus Tutorial in C to Communicate with Wpa_Supplicant
How to Write One Script That Runs in Bash/Shell and Powershell
How to Do Foreach *.Mp3 File Recursively in a Bash Script
Extract Average Time from Ping -C
Cross Compile from Linux to Arm-Elf (Arm926Ej-S/Mt7108)
Docker Alpine Executable Binary Not Found Even If in Path
How Does Copy_From_User from the Linux Kernel Work Internally
Can Ptrace Tell If an X86 System Call Used the 64-Bit or 32-Bit Abi
Accessing the Gpio (Of a Raspberry Pi) Without ''Sudo''
Filtering Rows Based on Number of Columns with Awk