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.)
What's the difference between [ and [[ in Bash?
[[
is bash's improvement to the [
command. It has several enhancements that make it a better choice if you write scripts that target bash. My favorites are:
It is a syntactical feature of the shell, so it has some special behavior that
[
doesn't have. You no longer have to quote variables like mad because[[
handles empty strings and strings with whitespace more intuitively. For example, with[
you have to writeif [ -f "$file" ]
to correctly handle empty strings or file names with spaces in them. With
[[
the quotes are unnecessary:if [[ -f $file ]]
Because it is a syntactical feature, it lets you use
&&
and||
operators for boolean tests and<
and>
for string comparisons.[
cannot do this because it is a regular command and&&
,||
,<
, and>
are not passed to regular commands as command-line arguments.It has a wonderful
=~
operator for doing regular expression matches. With[
you might writeif [ "$answer" = y -o "$answer" = yes ]
With
[[
you can write this asif [[ $answer =~ ^y(es)?$ ]]
It even lets you access the captured groups which it stores in
BASH_REMATCH
. For instance,${BASH_REMATCH[1]}
would be "es" if you typed a full "yes" above.You get pattern matching aka globbing for free. Maybe you're less strict about how to type yes. Maybe you're okay if the user types y-anything. Got you covered:
if [[ $ANSWER = y* ]]
Keep in mind that it is a bash extension, so if you are writing sh-compatible scripts then you need to stick with [
. Make sure you have the #!/bin/bash
shebang line for your script if you use double brackets.
See also
- Bash FAQ - "What is the difference between test, [ and [[ ?"
- Bash Practices - Bash Tests
- Server Fault - What is the difference between double and single brackets in bash?
What is the difference between $(command) and `command` in shell programming?
The backticks/gravemarks have been deprecated in favor of $()
for command substitution because $()
can easily nest within itself as in $(echo foo$(echo bar))
. There are other differences such as how backslashes are parsed in the backtick/gravemark version, etc.
See BashFAQ/082 for several reasons to always prefer the $(...) syntax.
Also see the POSIX spec for detailed information on the various differences.
What is the difference between ${var}, $var, and ${var} in the Bash shell?
Braces ($var
vs. ${var}
)
In most cases, $var
and ${var}
are the same:
var=foo
echo $var
# foo
echo ${var}
# foo
The braces are only needed to resolve ambiguity in expressions:
var=foo
echo $varbar
# Prints nothing because there is no variable 'varbar'
echo ${var}bar
# foobar
Quotes ($var
vs. "$var"
vs. "${var}"
)
When you add double quotes around a variable, you tell the shell to treat it as a single word, even if it contains whitespaces:
var="foo bar"
for i in "$var"; do # Expands to 'for i in "foo bar"; do...'
echo $i # so only runs the loop once
done
# foo bar
Contrast that behavior with the following:
var="foo bar"
for i in $var; do # Expands to 'for i in foo bar; do...'
echo $i # so runs the loop twice, once for each argument
done
# foo
# bar
As with $var
vs. ${var}
, the braces are only needed for disambiguation, for example:
var="foo bar"
for i in "$varbar"; do # Expands to 'for i in ""; do...' since there is no
echo $i # variable named 'varbar', so loop runs once and
done # prints nothing (actually "")
var="foo bar"
for i in "${var}bar"; do # Expands to 'for i in "foo barbar"; do...'
echo $i # so runs the loop once
done
# foo barbar
Note that "${var}bar"
in the second example above could also be written "${var}"bar
, in which case you don't need the braces anymore, i.e. "$var"bar
. However, if you have a lot of quotes in your string these alternative forms can get hard to read (and therefore hard to maintain). This page provides a good introduction to quoting in Bash.
Arrays ($var
vs. $var[@]
vs. ${var[@]}
)
Now for your array. According to the bash manual:
Referencing an array variable without a subscript is equivalent to referencing the array with a subscript of 0.
In other words, if you don't supply an index with []
, you get the first element of the array:
foo=(a b c)
echo $foo
# a
Which is exactly the same as
foo=(a b c)
echo ${foo}
# a
To get all the elements of an array, you need to use @
as the index, e.g. ${foo[@]}
. The braces are required with arrays because without them, the shell would expand the $foo
part first, giving the first element of the array followed by a literal [@]
:
foo=(a b c)
echo ${foo[@]}
# a b c
echo $foo[@]
# a[@]
This page is a good introduction to arrays in Bash.
Quotes revisited (${foo[@]}
vs. "${foo[@]}"
)
You didn't ask about this but it's a subtle difference that's good to know about. If the elements in your array could contain whitespace, you need to use double quotes so that each element is treated as a separate "word:"
foo=("the first" "the second")
for i in "${foo[@]}"; do # Expands to 'for i in "the first" "the second"; do...'
echo $i # so the loop runs twice
done
# the first
# the second
Contrast this with the behavior without double quotes:
foo=("the first" "the second")
for i in ${foo[@]}; do # Expands to 'for i in the first the second; do...'
echo $i # so the loop runs four times!
done
# the
# first
# the
# second
What is the difference between . and ./ in bash?
The shell uses spaces to separate the command to run and its parameters.
In the first example, the command to run is .
with a parameter of a.out
. The .
command is a shell shortcut for source
, which takes the name of a file containing shell commands as its first parameter and runs those commands in the current shell. This command fails because a.out
is a binary file, not a shell script.
In the second example, the command to run is ./a.out
, which means run the file a.out
residing in the current directory.
What is the difference between $VAR ${VAR} and $(VAR) in bash?
Let's take one command at a time:
echo $ABCHOME
The $
is a unary operator which indicates that expansion (or "substitution" if you like) is to take place. With no brackets it gives the value of the variable which follows. If the variable value contains whitespace then that whitespace will be used as an argument separator to the command, so I recommend:
echo "$ABCHOME"
Note: double quotes not single. Like brackets, different quote characters have different uses.
Using { }
:
echo ${ABCHOME}
With no other characters, the braces are used to delimit the variable name when embedded in other text, and are rarely required (although they are benign). For example: echo "$ABCHOMEandaway"
would fail, but echo "${ABCHOME}andaway"
would append "andaway" to the value text. The recommendations with quotes also apply here.
Braces, ${ }
also introduce other variable expansion syntax when the variable name is followed by a special character like a colon :
or a /
. That is probably too advanced for you right now, put that on your list for learning later.
Using $( )
:
echo $(ABCHOME)
This expansion is command substitution, where the command specified inside the parentheses is run and the standard output captured and returned to the script. Of course, there is no command called ABCHOME
, so you get:
bash: ABCHOME: command not found
As a general rule, brackets cannot be exchanged without thought in any programming language. Bash syntax can be complex and non-intuitive. Follow a tutorial (there are lots available). Play by all means, but use the man bash
pages to discover the syntax you are using.
What is the difference between backticks and $() in a Bash script?
There isn't any semantic difference. The backtick syntax is the older and less powerful version. See man bash, section "Command Substitution".
If your shell supports the $()
syntax, prefer it because it can be nested.
Difference between single and double quotes in Bash
Single quotes won't interpolate anything, but double quotes will. For example: variables, backticks, certain \
escapes, etc.
Example:
$ echo "$(echo "upg")"
upg
$ echo '$(echo "upg")'
$(echo "upg")
The Bash manual has this to say:
3.1.2.2 Single Quotes
Enclosing characters in single quotes (
'
) preserves the literal value of each character within the quotes. A single quote may not occur between single quotes, even when preceded by a backslash.3.1.2.3 Double Quotes
Enclosing characters in double quotes (
"
) preserves the literal value of all characters within the quotes, with the exception of$
,`
,\
, and, when history expansion is enabled,!
. The characters$
and`
retain their special meaning within double quotes (see Shell Expansions). The backslash retains its special meaning only when followed by one of the following characters:$
,`
,"
,\
, or newline. Within double quotes, backslashes that are followed by one of these characters are removed. Backslashes preceding characters without a special meaning are left unmodified. A double quote may be quoted within double quotes by preceding it with a backslash. If enabled, history expansion will be performed unless an!
appearing in double quotes is escaped using a backslash. The backslash preceding the!
is not removed.The special parameters
*
and@
have special meaning when in double quotes (see Shell Parameter Expansion).
Related Topics
./Configure: /Bin/Sh^M: Bad Interpreter
How to Get Overall Cpu Usage (E.G. 57%) on Linux
What Is Rss and Vsz in Linux Memory Management
Can Windows Containers Be Hosted on Linux
Have Bash Script Answer Interactive Prompts
Get Destination Address of a Received Udp Packet
What Is the Runtime Performance Cost of a Docker Container
Ld Cannot Find an Existing Library
Is There Any API For Determining the Physical Address from Virtual Address in Linux
"Failed to Load Platform Plugin "Xcb" " While Launching Qt5 App on Linux Without Qt Installed
How to Recursively Grep All Directories and Subdirectories
Finding Which Process Was Killed by Linux Oom Killer
How to Debug the Linux Kernel With Gdb and Qemu
What Happens If There Is No Exit System Call in an Assembly Program
How to Install Latest Version of Git on Centos 8.X/7.X/6.X