Hot answers tagged

260

An if statement typically looks like if commands1 then commands2 else commands3 fi The then clause is executed if the exit code of commands1 is zero. If the exit code is nonzero, then the else clause is executed. commands1 can be simple or complex. It can, for example, be a sequence of one or more pipelines separated by one of the operators ;, &...


97

In modern bash (version 4.2 and above): [[ -v name_of_var ]] From help test: -v VAR, True if the shell variable VAR is set


83

The single bracket [ is actually an alias for the test command, it's not syntax. One of the downsides (of many) of the single bracket is that if one or more of the operands it is trying to evaluate return an empty string, it will complain that it was expecting two operands (binary). This is why you see people do [ x$foo = x$blah ], the x guarantees that ...


77

(…) parentheses indicate a subshell. What's inside them isn't an expression like in many other languages. It's a list of commands (just like outside parentheses). These commands are executed in a separate subprocess, so any redirection, assignment, etc. performed inside the parentheses has no effect outside the parentheses. With a leading dollar sign, $(…) ...


63

The [ command's job is to evaluate test expressions. It returns with a 0 exit status (that means true) when the expression resolves to true and something else (which means false) otherwise. It's not that it does nothing, it's just that its outcome is to be found in its exit status. In a shell, you can find out about the exit status of the last command in $? ...


58

Your missing ]' error is because you need a space at the inbetween "Shared" and ], so the line should be if [ "$(ipcs | grep Shared | awk '{print $2}')" == "Shared" ]; then.


51

The [ command is an ordinary command. Although most shells provide it as a built-in for efficiency, it obeys the shell's normal syntactic rules. [ is exactly equivalent to test, except that [ requires a ] as its last argument and test doesn't. The double brackets [[ … ]] are special syntax. They were introduced in ksh (several years after [) because [ can ...


51

From the bash man page. When used with [[, the < and > operators sort lexicographically using the current locale. From the output, it appears to be working as designed.


46

The ~ is actually part of the operator =~ which performs a regular expression match of the string to its left to the extended regular expression on its right. [[ "string" =~ pattern ]] Note that the string should be quoted, and that the regular expression shouldn't be quoted. A similar operator is used in the Perl programming language. The regular ...


41

The difference between [[ … ]] and [ … ] is mostly covered in using single or double bracket - bash. Crucially, [[ … ]] is special syntax, whereas [ is a funny-looking name for a command. [[ … ]] has special syntax rules for what's inside, [ … ] doesn't. With the added wrinkle of a wildcard, here's how [[ $a == z* ]] is evaluated: Parse the command: this ...


41

I am always surprised that in the folder /bin there is a [ program. You are right to be surprised. That's one of the rare POSIX commands, with the null utility (:), that doesn't respect the commands file allowed characters convention (portable filename character set). Is is what is called when we are doing something like: if [ something ]? Precisely but ...


39

[ is an alias for the test command. Unix Version 6 had an if command, but Version 7 (1979) came with the new Bourne shell that had a few programming constructs including the if-then-else-elif-fi construct, and Unix version 7 added a test command that performed most of the "tests" that were carried out by the if command in older versions. [ was made an alias ...


39

[ -f /*.txt ] would return true only if there's one (and only one) non-hidden file in / whose name ends in .txt and if that file is a regular file or a symlink to a regular file. That's because wildcards are expanded by the shell prior to being passed to the command (here [). So if there's a /a.txt and /b.txt, [ will be passed 5 arguments: [, -f, /a.txt, /...


35

Portable to all POSIX shells: if [ -n "${foobar+1}" ]; then echo "foobar is defined" else echo "foobar is not defined" fi Make that ${foobar:+1} if you want to treat foobar the same way whether it is empty or not defined. You can also use ${foobar-} to get an empty string when foobar is undefined and the value of foobar otherwise (or put any other ...


35

Yes, there are differences. The most portable are test or [ ]. These are both part of the POSIX test specification. The if ... fi construct is also defined by POSIX and should be completely portable. The [[ ]] is a ksh feature that is also present in some versions of bash (all modern ones), in zsh and perhaps in others but is not present in sh or dash or ...


35

Beside the cosmetic/preference arguments, one reason could be that there are more implementations where [ ! "$a" = "$b" ] fails in corner cases than with [ "$a" != "$b" ]. Both cases should be safe if implementations follow the POSIX algorithm, but even today (early 2018 as of writing), there are still implementations that fail. For instance, with a='(' b=')...


35

You don't actually need the quotes here. This is one of the very few cases where it is safe to use a variable unquoted. You can confirm this with set -x: $ var1="" $ var2="3" $ set -x $ if [[ $var1 -eq $var2 ]]; then echo "match!"; else echo "no match!"; fi + [[ '' -eq 3 ]] + echo 'no match!' no match! $ if [[ "$var1" -eq "$var2" ]]; then echo "match!"; ...


33

Single square brackets in the shell is a synonym for test (either the separate command or the shell built-in), so [ 0 ] means the same thing as test 0. test is for doing comparisons and testing the attributes of files, as you can read about in its manpage. When it isn't given an expression that looks like a comparison, file test, or one of the other ...


33

In most cases, [ is a shell builtin and is equivalent to test. However, like test, it also exists as a standalone executable: that's the /bin/[ you saw. You can test this with type -a [ (on an Arch Linux system, running bash): $ type -a [ [ is a shell builtin [ is /bin/[ So, on my system, I have two [: my shell's builtin and the executable in /bin. The ...


31

-eq is an arithmetic operator, which compares two numbers. Use = (portable/standard sh), =~ or == instead. Also use quotes, because if ${PACKAGENAME} contains a whitespace or wildcard character, then it will be split into multiple arguments, which causes to make [ see more arguments than desired. See here a list of common bash pitfalls. if [ "${...


31

[ is synonym of the test command and it is simultaneously a bash builtin and separate command. But [[ is a bash keyword and works in some versions only. So for reasons of portability you are better off using single [] or test [ -w "/home/durrantm" ] && echo "writable"


30

I think you have have misunderstood what -w does. It does not check to see if the file has "Write permissions", it checks to see if the file is writable by the invoking user. More specifically, it calls access(2) or similar. eg if a script has if [ -w /etc/shadow ] then if you run strace on the script you may see a line similar to faccessat(AT_FDCWD, "/...


29

It's short for less than and greater than. It's used for integer comparison in bash. You can read more by typing man test: .... INTEGER1 -gt INTEGER2 INTEGER1 is greater than INTEGER2 .... INTEGER1 -lt INTEGER2 INTEGER1 is less than INTEGER2 ....


29

That's a consequence of those characters having the same sorting order. You'll also notice that sort -u << EOF ■ ⅕ ⅖ ⅗ EOF returns only one line. Or that: expr ■ = ⅕ returns true (as required by POSIX). Most locales shipped with GNU systems have a number of characters (and even sequences of characters (collating sequences)) that have the same ...


26

[ and test are synonyms (except [ requires ]), so you don't want to use [ test: [ -x /bin/cat ] && echo 'cat is executable' test -x /bin/cat && echo 'cat is executable' test returns a zero exit status if the condition is true, otherwise nonzero. This can actually be replaced by any program to check its exit status, where 0 indicates success ...


26

test -w aka [ -w doesn't check the file mode. It checks if it's writable. For root, it is. $ help test | grep '\-w' -w FILE True if the file is writable by you. The way I would test would be to do a bitwise comparison against the output of stat(1) ("%a Access rights in octal"). (( 0$(stat -c %a somefile) & 0200 )) && echo rw || ...


25

[ is neither a metacharacter nor a control operator (not even a reserved word; same for ]) thus it needs whitespace around it. Otherwise the shell "sees" the command [01=01] instead of the command [ with the separate parameters 01, =, 01, and ]. Each operator and operand needs to be a separate argument to the [ command, so whitespace is necessary around the ...


25

This is a very obscure corner case that one might consider a bug in how the test [ built-in is defined; however, it does match the behaviour of the actual [ binary available on many systems. As far as I can tell, it only affects certain cases and a variable having a value that matches a [ operator like (, !, =, -e, and so on. Let me explain why, and how to ...


Only top voted, non community-wiki answers of a minimum length are eligible