Difference Between Double and Single Bigger Than in Linux Terminal

Difference between single and double square brackets in Bash

Single [] are posix shell compliant condition tests.

Double [[]] are an extension to the standard [] and are supported by bash and other shells (e.g. zsh, ksh). They support extra operations (as well as the standard posix operations). For example: || instead of -o and regex matching with =~. A fuller list of differences can be found in the bash manual section on conditional constructs.

Use [] whenever you want your script to be portable across shells. Use [[]] if you want conditional expressions not supported by [] and don't need to be portable.

Are double square brackets [[ ]] preferable over single square brackets [ ] in Bash?

[[ has fewer surprises and is generally safer to use. But it is not portable - POSIX doesn't specify what it does and only some shells support it (beside bash, I heard ksh supports it too). For example, you can do

[[ -e $b ]]

to test whether a file exists. But with [, you have to quote $b, because it splits the argument and expands things like "a*" (where [[ takes it literally). That has also to do with how [ can be an external program and receives its argument just normally like every other program (although it can also be a builtin, but then it still has not this special handling).

[[ also has some other nice features, like regular expression matching with =~ along with operators like they are known in C-like languages. Here is a good page about it: What is the difference between test, [ and [[ ? and Bash Tests

How can I compare numbers in Bash?

In Bash, you should do your check in an arithmetic context:

if (( a > b )); then
...
fi

For POSIX shells that don't support (()), you can use -lt and -gt.

if [ "$a" -gt "$b" ]; then
...
fi

You can get a full list of comparison operators with help test or man test.

Why is [[ 10 2 ]] true when comparing numbers in bash?

Because you compare strings according to Lexicographical order and not numbers

You may use [[ 10 -lt 2 ]] and [[ 20 -lt 2 ]]. -lt stands for Less than (<). For Greater than (>) -gt notation can be used instead.

In bash double parenthesis can be used as well for performing numeric comparison:

if ((10 < 2)); then echo "yes"; else echo "no"; fi

The above example will echo no

Shell equality operators (=, ==, -eq)

= and == are for string comparisons

-eq is for numeric comparisons

-eq is in the same family as -lt, -le, -gt, -ge, and -ne

== is specific to bash (not present in sh (Bourne shell), ...). Using POSIX = is preferred for compatibility. In bash the two are equivalent, and in sh = is the only one that will work.

$ a=foo
$ [ "$a" = foo ]; echo "$?" # POSIX sh
0
$ [ "$a" == foo ]; echo "$?" # bash-specific
0
$ [ "$a" -eq foo ]; echo "$?" # wrong
-bash: [: foo: integer expression expected
2

(Note: make sure to quote the variable expansions. Do not leave out the double-quotes above.)

If you're writing a #!/bin/bash script then I recommend using [[ instead. The double square-brackets [[...]] form has more features, a more natural syntax, and fewer gotchas that will trip you up. For example, double quotes are no longer required around $a:

$ [[ $a == foo ]]; echo "$?"      # bash-specific
0

See also:

  • What's the difference between [ and [[ in Bash?

Single quote inside of double quoted string on linux command line

According to the bash man page:

   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.

So the answer is, you can't include a single quote within a single-quoted string no matter how you try. But depending on how your script is set up you may be able to use '\'', which will end the first single quote, escape the second, and start another single-quoted string with the third.

How to do a logical OR operation for integer comparison in shell scripting?

This should work:

#!/bin/bash

if [ "$#" -eq 0 ] || [ "$#" -gt 1 ] ; then
echo "hello"
fi

I'm not sure if this is different in other shells but if you wish to use <, >, you need to put them inside double parenthesis like so:

if (("$#" > 1))
...

Assumption with double quotes, single quotes & no quotes

It looks like you are looking for exceptions, and I'd guess you have some in mind. I'm going to make the assumption that set -f/set -o noglob are being excluded from this case?

When you use the dd command, globbing will not occure, even if unquoted.

$ ls *.txt
blah.txt file1.txt file2.txt file.txt logfile.txt
$ dd if=*.txt of=glob.txt
dd: failed to open ‘*.txt’: No such file or directory

Rebuttal and false positives

Here are some examples that are odd, but follow expansion

variable='2010-09-08 12:34:56'
echo "$variable" | xargs date +%s -d
date: extra operand '12:34:56'

The extra operand shows that variable expansion is happening, you are losing the quotes in the pipe.
$ date +%s -d 2010-09-08 12:34:56
date: extra operand ‘12:34:56’

This also happens if you create a script to echo $1 and then expand your quoted variable while passing. It expands, and works as expected. So, the issue is not with xargs, but with your expansion before the pipe which is normal.

  1. Eval... evals whole purpose is to do expansion of its args prior to running a command. Expansion also happens with bash -c, except it takes one argument. So, again, this is not an expansion issue, but a command usage issue.

cmd='printf "%s\n" "$(date -d "$variable" +%c)"'
bash -c $cmd

works the same as the expanded version

$ bash -c printf "%s\n" "$(date -d "$variable" +%c)"
printf: usage: printf [-v var] format [arguments]


  1. I really enjoyed Hauri's $'...' and $"..." information--however, those are not the samething we are talking about. They are in fact behaving as the bash man page says they should. $'' is as different from '' as (()) is from $(())

  2. I got excited about this one, so...
    $ ls
    mclark.txt qt sign_in.txt skel.bash
    $ zip m*t.zip *t
    $ ls *.zip
    m*t.zip

However, this isn't right either-- the splat expands, but upon no match zip uses it as a literal. I found a few commands that did this, but if there was a match (I added a my.zip later) it uses the matched expansion (an error was thrown, b/c my.zip was a text file for testing purposes).



Related Topics



Leave a reply



Submit