Variable with quotation marks “$()” Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern)What is the point of the bash Null-operator “:”, colon?Why does bash remove n in $(cat file)?What other bash variables are available during execution such as $USER that can assist on my script?Problem with script substitution when running scriptChange Gsetting with script on LogoutHow to link a custom keyboard shortcut to a bash script in Ubuntu 13.04?Can you help me to understand this explanation of shell quoting?Installing breach browserhow to fix my keyboard after a bash script messed it up[Edited/include]man: bash. e and bash shell “enter” tokenusing variable within quotation marksHow to get BASH to use * wildcard in command?
Can Pao de Queijo, and similar foods, be kosher for Passover?
Why was the term "discrete" used in discrete logarithm?
Is there a "higher Segal conjecture"?
How to find all the available tools in macOS terminal?
I am not a queen, who am I?
Why aren't air breathing engines used as small first stages
Why is "Captain Marvel" translated as male in Portugal?
Why are there no cargo aircraft with "flying wing" design?
What happens to sewage if there is no river near by?
What would be the ideal power source for a cybernetic eye?
"Seemed to had" is it correct?
Can a non-EU citizen traveling with me come with me through the EU passport line?
What is the longest distance a 13th-level monk can jump while attacking on the same turn?
How to bypass password on Windows XP account?
When -s is used with third person singular. What's its use in this context?
ListPlot join points by nearest neighbor rather than order
What is this single-engine low-wing propeller plane?
How do I keep my slimes from escaping their pens?
Is there a service that would inform me whenever a new direct route is scheduled from a given airport?
Models of set theory where not every set can be linearly ordered
Are my PIs rude or am I just being too sensitive?
When is phishing education going too far?
What causes the vertical darker bands in my photo?
Is the Standard Deduction better than Itemized when both are the same amount?
Variable with quotation marks “$()”
Announcing the arrival of Valued Associate #679: Cesar Manara
Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern)What is the point of the bash Null-operator “:”, colon?Why does bash remove n in $(cat file)?What other bash variables are available during execution such as $USER that can assist on my script?Problem with script substitution when running scriptChange Gsetting with script on LogoutHow to link a custom keyboard shortcut to a bash script in Ubuntu 13.04?Can you help me to understand this explanation of shell quoting?Installing breach browserhow to fix my keyboard after a bash script messed it up[Edited/include]man: bash. e and bash shell “enter” tokenusing variable within quotation marksHow to get BASH to use * wildcard in command?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
I wrote this script :
#!/bin/bash
while [ true ]
do
currentoutput="$(lsusb)"
if [ "$currentoutput" != "$lastoutput" ]
then
echo "" date and Time >> test.log
date +%x_r >> test.log
lastoutput="$(lsusb)"
lsusb >> test.log
fi
sleep 5
done
I'm a newbie trying to learn fast and I got a question about the variable’s quotation marks.
Put a variable between $(), I get it, but why are the quotation marks needed even in the if
statement? Is it to make a nested command?
bash scripts
New contributor
add a comment |
I wrote this script :
#!/bin/bash
while [ true ]
do
currentoutput="$(lsusb)"
if [ "$currentoutput" != "$lastoutput" ]
then
echo "" date and Time >> test.log
date +%x_r >> test.log
lastoutput="$(lsusb)"
lsusb >> test.log
fi
sleep 5
done
I'm a newbie trying to learn fast and I got a question about the variable’s quotation marks.
Put a variable between $(), I get it, but why are the quotation marks needed even in the if
statement? Is it to make a nested command?
bash scripts
New contributor
5
Note thatwhile [ true ]
does produce an infinite loop, but perhaps not for the reason you think it does;while [ false ]
also produces an infinite loop, because with a single argument,[ ... ]
succeeds if that argument is a non-empty string.while true
will actually run a command namedtrue
(which always succeeds).
– chepner
Apr 12 at 13:06
3
You don't put a variable inside$()
. You put a command inside$()
.
– Wildcard
Apr 12 at 20:19
add a comment |
I wrote this script :
#!/bin/bash
while [ true ]
do
currentoutput="$(lsusb)"
if [ "$currentoutput" != "$lastoutput" ]
then
echo "" date and Time >> test.log
date +%x_r >> test.log
lastoutput="$(lsusb)"
lsusb >> test.log
fi
sleep 5
done
I'm a newbie trying to learn fast and I got a question about the variable’s quotation marks.
Put a variable between $(), I get it, but why are the quotation marks needed even in the if
statement? Is it to make a nested command?
bash scripts
New contributor
I wrote this script :
#!/bin/bash
while [ true ]
do
currentoutput="$(lsusb)"
if [ "$currentoutput" != "$lastoutput" ]
then
echo "" date and Time >> test.log
date +%x_r >> test.log
lastoutput="$(lsusb)"
lsusb >> test.log
fi
sleep 5
done
I'm a newbie trying to learn fast and I got a question about the variable’s quotation marks.
Put a variable between $(), I get it, but why are the quotation marks needed even in the if
statement? Is it to make a nested command?
bash scripts
bash scripts
New contributor
New contributor
edited Apr 12 at 6:57
dessert
25.6k674108
25.6k674108
New contributor
asked Apr 12 at 5:11
ShankharaShankhara
613
613
New contributor
New contributor
5
Note thatwhile [ true ]
does produce an infinite loop, but perhaps not for the reason you think it does;while [ false ]
also produces an infinite loop, because with a single argument,[ ... ]
succeeds if that argument is a non-empty string.while true
will actually run a command namedtrue
(which always succeeds).
– chepner
Apr 12 at 13:06
3
You don't put a variable inside$()
. You put a command inside$()
.
– Wildcard
Apr 12 at 20:19
add a comment |
5
Note thatwhile [ true ]
does produce an infinite loop, but perhaps not for the reason you think it does;while [ false ]
also produces an infinite loop, because with a single argument,[ ... ]
succeeds if that argument is a non-empty string.while true
will actually run a command namedtrue
(which always succeeds).
– chepner
Apr 12 at 13:06
3
You don't put a variable inside$()
. You put a command inside$()
.
– Wildcard
Apr 12 at 20:19
5
5
Note that
while [ true ]
does produce an infinite loop, but perhaps not for the reason you think it does; while [ false ]
also produces an infinite loop, because with a single argument, [ ... ]
succeeds if that argument is a non-empty string. while true
will actually run a command named true
(which always succeeds).– chepner
Apr 12 at 13:06
Note that
while [ true ]
does produce an infinite loop, but perhaps not for the reason you think it does; while [ false ]
also produces an infinite loop, because with a single argument, [ ... ]
succeeds if that argument is a non-empty string. while true
will actually run a command named true
(which always succeeds).– chepner
Apr 12 at 13:06
3
3
You don't put a variable inside
$()
. You put a command inside $()
.– Wildcard
Apr 12 at 20:19
You don't put a variable inside
$()
. You put a command inside $()
.– Wildcard
Apr 12 at 20:19
add a comment |
4 Answers
4
active
oldest
votes
Quotation marks prevent "word splitting". That is: breaking down variables into multiple items at whitespace characters (or to be more exact, at spaces, tabs, and newlines as defined in the value of the default $IFS
shell variable).
For example,
$ var="one two"
$ howmany() echo $#;
$ howmany $var
2
$ howmany "$var"
1
Here we define the howmany
function which just lets us know how many positional parameters are given. As you can see, there are two items being passed to the variable, and with the quotes the text in the variable is treated as one unit.
This is important for accurate passing of information. For example, if the variable contains path to file, and the filename contains spaces anywhere in the path, the command you are trying to run may fail or give inaccurate results. If we were trying to create a file with the $var
variable, touch $var
would create two files, but touch "$var"
just one.
Same goes for your [ "$currentoutput" != "$lastoutput" ]
part. This particular test performs a comparison on two strings. When the test runs, the [
command would need to see 3 arguments - a text string, the !=
operator, and another text string. Keeping double quotes prevents word splitting, and the [
command sees exactly those 3 arguments. Now what happens if variables are unquoted ?
$ var="hello world"
$ foo="hi world"
$ [ $var != $foo ]
bash: [: too many arguments
$
Here, word splitting occurs, and instead [
sees two strings hello
and world
followed by !=
, followed by two other strings hi world
. Key point is that without double quotes, the contents of variables are understood as separate units rather than one whole item.
Assigning command substitution doesn't require double quotes as in
var=$( df )
where you have the df
command's output saved to var
. However, it is a good habit to always double quote variables and command substitution $(...)
unless you do in fact want the output to be treated as separate items.
On a side note, the
while [ true ]
part can be
while true
[
is a command which evaluates its arguments, and [ whatever ]
is always true regardless of what is inside. By contrast, while true
uses the command true
which always returns success exit status (and that's exactly what while
loop needs). The difference is a bit more clarity and less testing performed. Alternatively, you could also use :
instead of true
The double quotes in echo "" date and Time
part could probably be removed. They merely insert an empty string and an add extra space to the output. If that's desired, feel free to keep them there, but there's no particular functional value in this case.
lsusb >> test.log
This part could probably be replaced with echo "$currentoutput" >> test.log
. There's no reason to run lsusb
again after it has been run already in currentoutput=$(lsusb)
. In cases where trailing newlines
have to be preserved in the output - one could see the value in running a command multiple times, but in case of lsusb
there's no need for that. The less external commands you call, the better, because every call to a non-built-in command incurs costs in CPU, memory usage, and execution time ( even though the commands are probably pre-loaded from memory).
See also:
- When is double-quoting necessary?
- What is the point of the bash null operator : (colon)?
- Security implications of forgetting to quote a variable in bash/POSIX shells
Great answer, if you didn't already, you should write a book aboutbash
. But in the last part shouldn'techo "$currentoutput" >> test.log
better beprintf '%sn' "$currentoutput" >> test.log
?
– RoVo
Apr 12 at 7:05
1
@RoVo Yes,printf
should be preferred for portability. Since we're using bash-specific script here it can be excused to useecho
. But your observation is very much correct
– Sergiy Kolodyazhnyy
Apr 12 at 13:26
1
@SergiyKolodyazhnyy, ...I'm not sure thatecho
is completely reliable even when the shell is known to be bash (and the value of thexpg_echo
andposix
flags is known); if your value could be-n
or-e
, it can disappear instead of being printed.
– Charles Duffy
Apr 12 at 16:13
add a comment |
In currentoutput="$(lsusb)"
lsusb is not a variable, it is a command. What this statement does, it executes lsusb
command and assigns its output to currentoutput
variable.
Older syntax for this was
currentoutput=`lsusb`
you can find it in many examples and scripts
To answer the other part of your question, if [ ]
is just how syntax for if
is defined in bash. See more in https://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html
3
I think it's important to say that[ ]
is actually thetest
command. You can useif
statements with other commands too, as it relies on a 0 or non-zero test of their exit code.
– Arronical
Apr 12 at 9:08
...indeed, it's much better to runif grep -qe "somestring" file
than to rungrep -qe "somestring" file; if [ $? = 0 ]; then ...
, so the claim thatif [ ...
is part of the definition ofif
syntax is not just misleading but leads to bad practices.
– Charles Duffy
Apr 12 at 16:16
add a comment |
The following runs the external command command
and returns its output.
"$(command)"
Without the brackets/parentheses, this would look for a variable instead of running a command:
"$variable"
As for the difference between $variable
and "$variable"
, this becomes relevant when $variable
contains spaces. When using "$variable"
, the entire variable contents will be inserted into a single string even if the contents include spaces. When using $variable
the contents of the variable may be expanded into an argument list of multiple arguments.
HI @thomasrutter, I'm sorry, i meant quotation mark ... I edit my comment now !
– Shankhara
Apr 12 at 5:17
add a comment |
To be contrarian - bash recommends you use the [[ ... ]]
over the [ ... ]
construct to avoid having to quote variables in the test and so the associated problems of word splitting that the others have pointed out.
[
is provided in bash for POSIX compatibility with scripts meant to run under #!/bin/sh
or those being ported over to bash - for the most part, you should avoid it in favour of [[
.
e.g.
# With [ - quotes are needed
$ foo='one two'; bar='one two'; [ $foo = $bar ] && echo "they're equal"
-bash: [: too many arguments
$ foo='one two'; bar='one two'; [ "$foo" = "$bar" ] && echo "they're equal"
they're equal
# versus [[ - quotes not needed
$ foo='one two'; bar='one two'; [[ $foo = $bar ]] && echo "they're equal"
they're equal
bash
makes no such recommendation; it provides[[ ... ]]
which can be more convenient and has some functionality that[ ... ]
does not, but there is no problem with using[ ... ]
correctly.
– chepner
Apr 12 at 13:01
@chepner - Maybe I should be clearer here. Sure it's not an explicit recommendation in the bash manpage but given[[
does everything[
does and more and still the many times[
trips people up and then try and retrofit features of[[
back to[
only to fail and leave bugs scattered about - it's fair to say it is a community recommendation in as far as most relevant bash style guides will advise never use[
.
– shalomb
Apr 12 at 14:36
add a comment |
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "89"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Shankhara is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2faskubuntu.com%2fquestions%2f1133173%2fvariable-with-quotation-marks%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
Quotation marks prevent "word splitting". That is: breaking down variables into multiple items at whitespace characters (or to be more exact, at spaces, tabs, and newlines as defined in the value of the default $IFS
shell variable).
For example,
$ var="one two"
$ howmany() echo $#;
$ howmany $var
2
$ howmany "$var"
1
Here we define the howmany
function which just lets us know how many positional parameters are given. As you can see, there are two items being passed to the variable, and with the quotes the text in the variable is treated as one unit.
This is important for accurate passing of information. For example, if the variable contains path to file, and the filename contains spaces anywhere in the path, the command you are trying to run may fail or give inaccurate results. If we were trying to create a file with the $var
variable, touch $var
would create two files, but touch "$var"
just one.
Same goes for your [ "$currentoutput" != "$lastoutput" ]
part. This particular test performs a comparison on two strings. When the test runs, the [
command would need to see 3 arguments - a text string, the !=
operator, and another text string. Keeping double quotes prevents word splitting, and the [
command sees exactly those 3 arguments. Now what happens if variables are unquoted ?
$ var="hello world"
$ foo="hi world"
$ [ $var != $foo ]
bash: [: too many arguments
$
Here, word splitting occurs, and instead [
sees two strings hello
and world
followed by !=
, followed by two other strings hi world
. Key point is that without double quotes, the contents of variables are understood as separate units rather than one whole item.
Assigning command substitution doesn't require double quotes as in
var=$( df )
where you have the df
command's output saved to var
. However, it is a good habit to always double quote variables and command substitution $(...)
unless you do in fact want the output to be treated as separate items.
On a side note, the
while [ true ]
part can be
while true
[
is a command which evaluates its arguments, and [ whatever ]
is always true regardless of what is inside. By contrast, while true
uses the command true
which always returns success exit status (and that's exactly what while
loop needs). The difference is a bit more clarity and less testing performed. Alternatively, you could also use :
instead of true
The double quotes in echo "" date and Time
part could probably be removed. They merely insert an empty string and an add extra space to the output. If that's desired, feel free to keep them there, but there's no particular functional value in this case.
lsusb >> test.log
This part could probably be replaced with echo "$currentoutput" >> test.log
. There's no reason to run lsusb
again after it has been run already in currentoutput=$(lsusb)
. In cases where trailing newlines
have to be preserved in the output - one could see the value in running a command multiple times, but in case of lsusb
there's no need for that. The less external commands you call, the better, because every call to a non-built-in command incurs costs in CPU, memory usage, and execution time ( even though the commands are probably pre-loaded from memory).
See also:
- When is double-quoting necessary?
- What is the point of the bash null operator : (colon)?
- Security implications of forgetting to quote a variable in bash/POSIX shells
Great answer, if you didn't already, you should write a book aboutbash
. But in the last part shouldn'techo "$currentoutput" >> test.log
better beprintf '%sn' "$currentoutput" >> test.log
?
– RoVo
Apr 12 at 7:05
1
@RoVo Yes,printf
should be preferred for portability. Since we're using bash-specific script here it can be excused to useecho
. But your observation is very much correct
– Sergiy Kolodyazhnyy
Apr 12 at 13:26
1
@SergiyKolodyazhnyy, ...I'm not sure thatecho
is completely reliable even when the shell is known to be bash (and the value of thexpg_echo
andposix
flags is known); if your value could be-n
or-e
, it can disappear instead of being printed.
– Charles Duffy
Apr 12 at 16:13
add a comment |
Quotation marks prevent "word splitting". That is: breaking down variables into multiple items at whitespace characters (or to be more exact, at spaces, tabs, and newlines as defined in the value of the default $IFS
shell variable).
For example,
$ var="one two"
$ howmany() echo $#;
$ howmany $var
2
$ howmany "$var"
1
Here we define the howmany
function which just lets us know how many positional parameters are given. As you can see, there are two items being passed to the variable, and with the quotes the text in the variable is treated as one unit.
This is important for accurate passing of information. For example, if the variable contains path to file, and the filename contains spaces anywhere in the path, the command you are trying to run may fail or give inaccurate results. If we were trying to create a file with the $var
variable, touch $var
would create two files, but touch "$var"
just one.
Same goes for your [ "$currentoutput" != "$lastoutput" ]
part. This particular test performs a comparison on two strings. When the test runs, the [
command would need to see 3 arguments - a text string, the !=
operator, and another text string. Keeping double quotes prevents word splitting, and the [
command sees exactly those 3 arguments. Now what happens if variables are unquoted ?
$ var="hello world"
$ foo="hi world"
$ [ $var != $foo ]
bash: [: too many arguments
$
Here, word splitting occurs, and instead [
sees two strings hello
and world
followed by !=
, followed by two other strings hi world
. Key point is that without double quotes, the contents of variables are understood as separate units rather than one whole item.
Assigning command substitution doesn't require double quotes as in
var=$( df )
where you have the df
command's output saved to var
. However, it is a good habit to always double quote variables and command substitution $(...)
unless you do in fact want the output to be treated as separate items.
On a side note, the
while [ true ]
part can be
while true
[
is a command which evaluates its arguments, and [ whatever ]
is always true regardless of what is inside. By contrast, while true
uses the command true
which always returns success exit status (and that's exactly what while
loop needs). The difference is a bit more clarity and less testing performed. Alternatively, you could also use :
instead of true
The double quotes in echo "" date and Time
part could probably be removed. They merely insert an empty string and an add extra space to the output. If that's desired, feel free to keep them there, but there's no particular functional value in this case.
lsusb >> test.log
This part could probably be replaced with echo "$currentoutput" >> test.log
. There's no reason to run lsusb
again after it has been run already in currentoutput=$(lsusb)
. In cases where trailing newlines
have to be preserved in the output - one could see the value in running a command multiple times, but in case of lsusb
there's no need for that. The less external commands you call, the better, because every call to a non-built-in command incurs costs in CPU, memory usage, and execution time ( even though the commands are probably pre-loaded from memory).
See also:
- When is double-quoting necessary?
- What is the point of the bash null operator : (colon)?
- Security implications of forgetting to quote a variable in bash/POSIX shells
Great answer, if you didn't already, you should write a book aboutbash
. But in the last part shouldn'techo "$currentoutput" >> test.log
better beprintf '%sn' "$currentoutput" >> test.log
?
– RoVo
Apr 12 at 7:05
1
@RoVo Yes,printf
should be preferred for portability. Since we're using bash-specific script here it can be excused to useecho
. But your observation is very much correct
– Sergiy Kolodyazhnyy
Apr 12 at 13:26
1
@SergiyKolodyazhnyy, ...I'm not sure thatecho
is completely reliable even when the shell is known to be bash (and the value of thexpg_echo
andposix
flags is known); if your value could be-n
or-e
, it can disappear instead of being printed.
– Charles Duffy
Apr 12 at 16:13
add a comment |
Quotation marks prevent "word splitting". That is: breaking down variables into multiple items at whitespace characters (or to be more exact, at spaces, tabs, and newlines as defined in the value of the default $IFS
shell variable).
For example,
$ var="one two"
$ howmany() echo $#;
$ howmany $var
2
$ howmany "$var"
1
Here we define the howmany
function which just lets us know how many positional parameters are given. As you can see, there are two items being passed to the variable, and with the quotes the text in the variable is treated as one unit.
This is important for accurate passing of information. For example, if the variable contains path to file, and the filename contains spaces anywhere in the path, the command you are trying to run may fail or give inaccurate results. If we were trying to create a file with the $var
variable, touch $var
would create two files, but touch "$var"
just one.
Same goes for your [ "$currentoutput" != "$lastoutput" ]
part. This particular test performs a comparison on two strings. When the test runs, the [
command would need to see 3 arguments - a text string, the !=
operator, and another text string. Keeping double quotes prevents word splitting, and the [
command sees exactly those 3 arguments. Now what happens if variables are unquoted ?
$ var="hello world"
$ foo="hi world"
$ [ $var != $foo ]
bash: [: too many arguments
$
Here, word splitting occurs, and instead [
sees two strings hello
and world
followed by !=
, followed by two other strings hi world
. Key point is that without double quotes, the contents of variables are understood as separate units rather than one whole item.
Assigning command substitution doesn't require double quotes as in
var=$( df )
where you have the df
command's output saved to var
. However, it is a good habit to always double quote variables and command substitution $(...)
unless you do in fact want the output to be treated as separate items.
On a side note, the
while [ true ]
part can be
while true
[
is a command which evaluates its arguments, and [ whatever ]
is always true regardless of what is inside. By contrast, while true
uses the command true
which always returns success exit status (and that's exactly what while
loop needs). The difference is a bit more clarity and less testing performed. Alternatively, you could also use :
instead of true
The double quotes in echo "" date and Time
part could probably be removed. They merely insert an empty string and an add extra space to the output. If that's desired, feel free to keep them there, but there's no particular functional value in this case.
lsusb >> test.log
This part could probably be replaced with echo "$currentoutput" >> test.log
. There's no reason to run lsusb
again after it has been run already in currentoutput=$(lsusb)
. In cases where trailing newlines
have to be preserved in the output - one could see the value in running a command multiple times, but in case of lsusb
there's no need for that. The less external commands you call, the better, because every call to a non-built-in command incurs costs in CPU, memory usage, and execution time ( even though the commands are probably pre-loaded from memory).
See also:
- When is double-quoting necessary?
- What is the point of the bash null operator : (colon)?
- Security implications of forgetting to quote a variable in bash/POSIX shells
Quotation marks prevent "word splitting". That is: breaking down variables into multiple items at whitespace characters (or to be more exact, at spaces, tabs, and newlines as defined in the value of the default $IFS
shell variable).
For example,
$ var="one two"
$ howmany() echo $#;
$ howmany $var
2
$ howmany "$var"
1
Here we define the howmany
function which just lets us know how many positional parameters are given. As you can see, there are two items being passed to the variable, and with the quotes the text in the variable is treated as one unit.
This is important for accurate passing of information. For example, if the variable contains path to file, and the filename contains spaces anywhere in the path, the command you are trying to run may fail or give inaccurate results. If we were trying to create a file with the $var
variable, touch $var
would create two files, but touch "$var"
just one.
Same goes for your [ "$currentoutput" != "$lastoutput" ]
part. This particular test performs a comparison on two strings. When the test runs, the [
command would need to see 3 arguments - a text string, the !=
operator, and another text string. Keeping double quotes prevents word splitting, and the [
command sees exactly those 3 arguments. Now what happens if variables are unquoted ?
$ var="hello world"
$ foo="hi world"
$ [ $var != $foo ]
bash: [: too many arguments
$
Here, word splitting occurs, and instead [
sees two strings hello
and world
followed by !=
, followed by two other strings hi world
. Key point is that without double quotes, the contents of variables are understood as separate units rather than one whole item.
Assigning command substitution doesn't require double quotes as in
var=$( df )
where you have the df
command's output saved to var
. However, it is a good habit to always double quote variables and command substitution $(...)
unless you do in fact want the output to be treated as separate items.
On a side note, the
while [ true ]
part can be
while true
[
is a command which evaluates its arguments, and [ whatever ]
is always true regardless of what is inside. By contrast, while true
uses the command true
which always returns success exit status (and that's exactly what while
loop needs). The difference is a bit more clarity and less testing performed. Alternatively, you could also use :
instead of true
The double quotes in echo "" date and Time
part could probably be removed. They merely insert an empty string and an add extra space to the output. If that's desired, feel free to keep them there, but there's no particular functional value in this case.
lsusb >> test.log
This part could probably be replaced with echo "$currentoutput" >> test.log
. There's no reason to run lsusb
again after it has been run already in currentoutput=$(lsusb)
. In cases where trailing newlines
have to be preserved in the output - one could see the value in running a command multiple times, but in case of lsusb
there's no need for that. The less external commands you call, the better, because every call to a non-built-in command incurs costs in CPU, memory usage, and execution time ( even though the commands are probably pre-loaded from memory).
See also:
- When is double-quoting necessary?
- What is the point of the bash null operator : (colon)?
- Security implications of forgetting to quote a variable in bash/POSIX shells
edited Apr 12 at 10:57
terdon♦
67.8k13139223
67.8k13139223
answered Apr 12 at 5:50
Sergiy KolodyazhnyySergiy Kolodyazhnyy
75.5k9156330
75.5k9156330
Great answer, if you didn't already, you should write a book aboutbash
. But in the last part shouldn'techo "$currentoutput" >> test.log
better beprintf '%sn' "$currentoutput" >> test.log
?
– RoVo
Apr 12 at 7:05
1
@RoVo Yes,printf
should be preferred for portability. Since we're using bash-specific script here it can be excused to useecho
. But your observation is very much correct
– Sergiy Kolodyazhnyy
Apr 12 at 13:26
1
@SergiyKolodyazhnyy, ...I'm not sure thatecho
is completely reliable even when the shell is known to be bash (and the value of thexpg_echo
andposix
flags is known); if your value could be-n
or-e
, it can disappear instead of being printed.
– Charles Duffy
Apr 12 at 16:13
add a comment |
Great answer, if you didn't already, you should write a book aboutbash
. But in the last part shouldn'techo "$currentoutput" >> test.log
better beprintf '%sn' "$currentoutput" >> test.log
?
– RoVo
Apr 12 at 7:05
1
@RoVo Yes,printf
should be preferred for portability. Since we're using bash-specific script here it can be excused to useecho
. But your observation is very much correct
– Sergiy Kolodyazhnyy
Apr 12 at 13:26
1
@SergiyKolodyazhnyy, ...I'm not sure thatecho
is completely reliable even when the shell is known to be bash (and the value of thexpg_echo
andposix
flags is known); if your value could be-n
or-e
, it can disappear instead of being printed.
– Charles Duffy
Apr 12 at 16:13
Great answer, if you didn't already, you should write a book about
bash
. But in the last part shouldn't echo "$currentoutput" >> test.log
better be printf '%sn' "$currentoutput" >> test.log
?– RoVo
Apr 12 at 7:05
Great answer, if you didn't already, you should write a book about
bash
. But in the last part shouldn't echo "$currentoutput" >> test.log
better be printf '%sn' "$currentoutput" >> test.log
?– RoVo
Apr 12 at 7:05
1
1
@RoVo Yes,
printf
should be preferred for portability. Since we're using bash-specific script here it can be excused to use echo
. But your observation is very much correct– Sergiy Kolodyazhnyy
Apr 12 at 13:26
@RoVo Yes,
printf
should be preferred for portability. Since we're using bash-specific script here it can be excused to use echo
. But your observation is very much correct– Sergiy Kolodyazhnyy
Apr 12 at 13:26
1
1
@SergiyKolodyazhnyy, ...I'm not sure that
echo
is completely reliable even when the shell is known to be bash (and the value of the xpg_echo
and posix
flags is known); if your value could be -n
or -e
, it can disappear instead of being printed.– Charles Duffy
Apr 12 at 16:13
@SergiyKolodyazhnyy, ...I'm not sure that
echo
is completely reliable even when the shell is known to be bash (and the value of the xpg_echo
and posix
flags is known); if your value could be -n
or -e
, it can disappear instead of being printed.– Charles Duffy
Apr 12 at 16:13
add a comment |
In currentoutput="$(lsusb)"
lsusb is not a variable, it is a command. What this statement does, it executes lsusb
command and assigns its output to currentoutput
variable.
Older syntax for this was
currentoutput=`lsusb`
you can find it in many examples and scripts
To answer the other part of your question, if [ ]
is just how syntax for if
is defined in bash. See more in https://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html
3
I think it's important to say that[ ]
is actually thetest
command. You can useif
statements with other commands too, as it relies on a 0 or non-zero test of their exit code.
– Arronical
Apr 12 at 9:08
...indeed, it's much better to runif grep -qe "somestring" file
than to rungrep -qe "somestring" file; if [ $? = 0 ]; then ...
, so the claim thatif [ ...
is part of the definition ofif
syntax is not just misleading but leads to bad practices.
– Charles Duffy
Apr 12 at 16:16
add a comment |
In currentoutput="$(lsusb)"
lsusb is not a variable, it is a command. What this statement does, it executes lsusb
command and assigns its output to currentoutput
variable.
Older syntax for this was
currentoutput=`lsusb`
you can find it in many examples and scripts
To answer the other part of your question, if [ ]
is just how syntax for if
is defined in bash. See more in https://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html
3
I think it's important to say that[ ]
is actually thetest
command. You can useif
statements with other commands too, as it relies on a 0 or non-zero test of their exit code.
– Arronical
Apr 12 at 9:08
...indeed, it's much better to runif grep -qe "somestring" file
than to rungrep -qe "somestring" file; if [ $? = 0 ]; then ...
, so the claim thatif [ ...
is part of the definition ofif
syntax is not just misleading but leads to bad practices.
– Charles Duffy
Apr 12 at 16:16
add a comment |
In currentoutput="$(lsusb)"
lsusb is not a variable, it is a command. What this statement does, it executes lsusb
command and assigns its output to currentoutput
variable.
Older syntax for this was
currentoutput=`lsusb`
you can find it in many examples and scripts
To answer the other part of your question, if [ ]
is just how syntax for if
is defined in bash. See more in https://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html
In currentoutput="$(lsusb)"
lsusb is not a variable, it is a command. What this statement does, it executes lsusb
command and assigns its output to currentoutput
variable.
Older syntax for this was
currentoutput=`lsusb`
you can find it in many examples and scripts
To answer the other part of your question, if [ ]
is just how syntax for if
is defined in bash. See more in https://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html
answered Apr 12 at 5:17
marosgmarosg
47437
47437
3
I think it's important to say that[ ]
is actually thetest
command. You can useif
statements with other commands too, as it relies on a 0 or non-zero test of their exit code.
– Arronical
Apr 12 at 9:08
...indeed, it's much better to runif grep -qe "somestring" file
than to rungrep -qe "somestring" file; if [ $? = 0 ]; then ...
, so the claim thatif [ ...
is part of the definition ofif
syntax is not just misleading but leads to bad practices.
– Charles Duffy
Apr 12 at 16:16
add a comment |
3
I think it's important to say that[ ]
is actually thetest
command. You can useif
statements with other commands too, as it relies on a 0 or non-zero test of their exit code.
– Arronical
Apr 12 at 9:08
...indeed, it's much better to runif grep -qe "somestring" file
than to rungrep -qe "somestring" file; if [ $? = 0 ]; then ...
, so the claim thatif [ ...
is part of the definition ofif
syntax is not just misleading but leads to bad practices.
– Charles Duffy
Apr 12 at 16:16
3
3
I think it's important to say that
[ ]
is actually the test
command. You can use if
statements with other commands too, as it relies on a 0 or non-zero test of their exit code.– Arronical
Apr 12 at 9:08
I think it's important to say that
[ ]
is actually the test
command. You can use if
statements with other commands too, as it relies on a 0 or non-zero test of their exit code.– Arronical
Apr 12 at 9:08
...indeed, it's much better to run
if grep -qe "somestring" file
than to run grep -qe "somestring" file; if [ $? = 0 ]; then ...
, so the claim that if [ ...
is part of the definition of if
syntax is not just misleading but leads to bad practices.– Charles Duffy
Apr 12 at 16:16
...indeed, it's much better to run
if grep -qe "somestring" file
than to run grep -qe "somestring" file; if [ $? = 0 ]; then ...
, so the claim that if [ ...
is part of the definition of if
syntax is not just misleading but leads to bad practices.– Charles Duffy
Apr 12 at 16:16
add a comment |
The following runs the external command command
and returns its output.
"$(command)"
Without the brackets/parentheses, this would look for a variable instead of running a command:
"$variable"
As for the difference between $variable
and "$variable"
, this becomes relevant when $variable
contains spaces. When using "$variable"
, the entire variable contents will be inserted into a single string even if the contents include spaces. When using $variable
the contents of the variable may be expanded into an argument list of multiple arguments.
HI @thomasrutter, I'm sorry, i meant quotation mark ... I edit my comment now !
– Shankhara
Apr 12 at 5:17
add a comment |
The following runs the external command command
and returns its output.
"$(command)"
Without the brackets/parentheses, this would look for a variable instead of running a command:
"$variable"
As for the difference between $variable
and "$variable"
, this becomes relevant when $variable
contains spaces. When using "$variable"
, the entire variable contents will be inserted into a single string even if the contents include spaces. When using $variable
the contents of the variable may be expanded into an argument list of multiple arguments.
HI @thomasrutter, I'm sorry, i meant quotation mark ... I edit my comment now !
– Shankhara
Apr 12 at 5:17
add a comment |
The following runs the external command command
and returns its output.
"$(command)"
Without the brackets/parentheses, this would look for a variable instead of running a command:
"$variable"
As for the difference between $variable
and "$variable"
, this becomes relevant when $variable
contains spaces. When using "$variable"
, the entire variable contents will be inserted into a single string even if the contents include spaces. When using $variable
the contents of the variable may be expanded into an argument list of multiple arguments.
The following runs the external command command
and returns its output.
"$(command)"
Without the brackets/parentheses, this would look for a variable instead of running a command:
"$variable"
As for the difference between $variable
and "$variable"
, this becomes relevant when $variable
contains spaces. When using "$variable"
, the entire variable contents will be inserted into a single string even if the contents include spaces. When using $variable
the contents of the variable may be expanded into an argument list of multiple arguments.
edited Apr 12 at 5:18
answered Apr 12 at 5:14
thomasrutterthomasrutter
27.3k47089
27.3k47089
HI @thomasrutter, I'm sorry, i meant quotation mark ... I edit my comment now !
– Shankhara
Apr 12 at 5:17
add a comment |
HI @thomasrutter, I'm sorry, i meant quotation mark ... I edit my comment now !
– Shankhara
Apr 12 at 5:17
HI @thomasrutter, I'm sorry, i meant quotation mark ... I edit my comment now !
– Shankhara
Apr 12 at 5:17
HI @thomasrutter, I'm sorry, i meant quotation mark ... I edit my comment now !
– Shankhara
Apr 12 at 5:17
add a comment |
To be contrarian - bash recommends you use the [[ ... ]]
over the [ ... ]
construct to avoid having to quote variables in the test and so the associated problems of word splitting that the others have pointed out.
[
is provided in bash for POSIX compatibility with scripts meant to run under #!/bin/sh
or those being ported over to bash - for the most part, you should avoid it in favour of [[
.
e.g.
# With [ - quotes are needed
$ foo='one two'; bar='one two'; [ $foo = $bar ] && echo "they're equal"
-bash: [: too many arguments
$ foo='one two'; bar='one two'; [ "$foo" = "$bar" ] && echo "they're equal"
they're equal
# versus [[ - quotes not needed
$ foo='one two'; bar='one two'; [[ $foo = $bar ]] && echo "they're equal"
they're equal
bash
makes no such recommendation; it provides[[ ... ]]
which can be more convenient and has some functionality that[ ... ]
does not, but there is no problem with using[ ... ]
correctly.
– chepner
Apr 12 at 13:01
@chepner - Maybe I should be clearer here. Sure it's not an explicit recommendation in the bash manpage but given[[
does everything[
does and more and still the many times[
trips people up and then try and retrofit features of[[
back to[
only to fail and leave bugs scattered about - it's fair to say it is a community recommendation in as far as most relevant bash style guides will advise never use[
.
– shalomb
Apr 12 at 14:36
add a comment |
To be contrarian - bash recommends you use the [[ ... ]]
over the [ ... ]
construct to avoid having to quote variables in the test and so the associated problems of word splitting that the others have pointed out.
[
is provided in bash for POSIX compatibility with scripts meant to run under #!/bin/sh
or those being ported over to bash - for the most part, you should avoid it in favour of [[
.
e.g.
# With [ - quotes are needed
$ foo='one two'; bar='one two'; [ $foo = $bar ] && echo "they're equal"
-bash: [: too many arguments
$ foo='one two'; bar='one two'; [ "$foo" = "$bar" ] && echo "they're equal"
they're equal
# versus [[ - quotes not needed
$ foo='one two'; bar='one two'; [[ $foo = $bar ]] && echo "they're equal"
they're equal
bash
makes no such recommendation; it provides[[ ... ]]
which can be more convenient and has some functionality that[ ... ]
does not, but there is no problem with using[ ... ]
correctly.
– chepner
Apr 12 at 13:01
@chepner - Maybe I should be clearer here. Sure it's not an explicit recommendation in the bash manpage but given[[
does everything[
does and more and still the many times[
trips people up and then try and retrofit features of[[
back to[
only to fail and leave bugs scattered about - it's fair to say it is a community recommendation in as far as most relevant bash style guides will advise never use[
.
– shalomb
Apr 12 at 14:36
add a comment |
To be contrarian - bash recommends you use the [[ ... ]]
over the [ ... ]
construct to avoid having to quote variables in the test and so the associated problems of word splitting that the others have pointed out.
[
is provided in bash for POSIX compatibility with scripts meant to run under #!/bin/sh
or those being ported over to bash - for the most part, you should avoid it in favour of [[
.
e.g.
# With [ - quotes are needed
$ foo='one two'; bar='one two'; [ $foo = $bar ] && echo "they're equal"
-bash: [: too many arguments
$ foo='one two'; bar='one two'; [ "$foo" = "$bar" ] && echo "they're equal"
they're equal
# versus [[ - quotes not needed
$ foo='one two'; bar='one two'; [[ $foo = $bar ]] && echo "they're equal"
they're equal
To be contrarian - bash recommends you use the [[ ... ]]
over the [ ... ]
construct to avoid having to quote variables in the test and so the associated problems of word splitting that the others have pointed out.
[
is provided in bash for POSIX compatibility with scripts meant to run under #!/bin/sh
or those being ported over to bash - for the most part, you should avoid it in favour of [[
.
e.g.
# With [ - quotes are needed
$ foo='one two'; bar='one two'; [ $foo = $bar ] && echo "they're equal"
-bash: [: too many arguments
$ foo='one two'; bar='one two'; [ "$foo" = "$bar" ] && echo "they're equal"
they're equal
# versus [[ - quotes not needed
$ foo='one two'; bar='one two'; [[ $foo = $bar ]] && echo "they're equal"
they're equal
answered Apr 12 at 12:56
shalombshalomb
1814
1814
bash
makes no such recommendation; it provides[[ ... ]]
which can be more convenient and has some functionality that[ ... ]
does not, but there is no problem with using[ ... ]
correctly.
– chepner
Apr 12 at 13:01
@chepner - Maybe I should be clearer here. Sure it's not an explicit recommendation in the bash manpage but given[[
does everything[
does and more and still the many times[
trips people up and then try and retrofit features of[[
back to[
only to fail and leave bugs scattered about - it's fair to say it is a community recommendation in as far as most relevant bash style guides will advise never use[
.
– shalomb
Apr 12 at 14:36
add a comment |
bash
makes no such recommendation; it provides[[ ... ]]
which can be more convenient and has some functionality that[ ... ]
does not, but there is no problem with using[ ... ]
correctly.
– chepner
Apr 12 at 13:01
@chepner - Maybe I should be clearer here. Sure it's not an explicit recommendation in the bash manpage but given[[
does everything[
does and more and still the many times[
trips people up and then try and retrofit features of[[
back to[
only to fail and leave bugs scattered about - it's fair to say it is a community recommendation in as far as most relevant bash style guides will advise never use[
.
– shalomb
Apr 12 at 14:36
bash
makes no such recommendation; it provides [[ ... ]]
which can be more convenient and has some functionality that [ ... ]
does not, but there is no problem with using [ ... ]
correctly.– chepner
Apr 12 at 13:01
bash
makes no such recommendation; it provides [[ ... ]]
which can be more convenient and has some functionality that [ ... ]
does not, but there is no problem with using [ ... ]
correctly.– chepner
Apr 12 at 13:01
@chepner - Maybe I should be clearer here. Sure it's not an explicit recommendation in the bash manpage but given
[[
does everything [
does and more and still the many times [
trips people up and then try and retrofit features of [[
back to [
only to fail and leave bugs scattered about - it's fair to say it is a community recommendation in as far as most relevant bash style guides will advise never use [
.– shalomb
Apr 12 at 14:36
@chepner - Maybe I should be clearer here. Sure it's not an explicit recommendation in the bash manpage but given
[[
does everything [
does and more and still the many times [
trips people up and then try and retrofit features of [[
back to [
only to fail and leave bugs scattered about - it's fair to say it is a community recommendation in as far as most relevant bash style guides will advise never use [
.– shalomb
Apr 12 at 14:36
add a comment |
Shankhara is a new contributor. Be nice, and check out our Code of Conduct.
Shankhara is a new contributor. Be nice, and check out our Code of Conduct.
Shankhara is a new contributor. Be nice, and check out our Code of Conduct.
Shankhara is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Ask Ubuntu!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2faskubuntu.com%2fquestions%2f1133173%2fvariable-with-quotation-marks%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
5
Note that
while [ true ]
does produce an infinite loop, but perhaps not for the reason you think it does;while [ false ]
also produces an infinite loop, because with a single argument,[ ... ]
succeeds if that argument is a non-empty string.while true
will actually run a command namedtrue
(which always succeeds).– chepner
Apr 12 at 13:06
3
You don't put a variable inside
$()
. You put a command inside$()
.– Wildcard
Apr 12 at 20:19