|
Home | Switchboard | Unix Administration | Red Hat | TCP/IP Networks | Neoliberalism | Toxic Managers |
(slightly skeptical) Educational society promoting "Back to basics" movement against IT overcomplexity and bastardization of classic Unix |
|
Note: Those are my old lecture notes for FDU students. They use copyrighted examples from several sources such as Advanced Bash-Scripting Guide and as such can be used for educational purposes only in accordance with fair use doctrine.
Each command is bash produces so called return code which indicates whether the command was executed successfully. It is stored in a special system variable named $?. In this case the command executed successfully returns zero. It there some problems the result in not zero and higher is the number the more severe error was encountered during the execution of command. This is a very useful information in scripts, but we need somehow to check this variable. The if command provides this opportunity.
The built-in if command runs a command and checks the resulting return code. If return code is zero (the command was successful), it executes then branch. If it is non-zero it executed else branch if it exists.
Any Unix utility or command can be used with the if command, not only test.
The syntax of Bash if command is as follows
if test arguments ; then # statements to run if test succeed (the command returned RC=0) else # statements to run if the text failed (return RC >0) fiEssentially that means *Using modern bash double round quote expressions):
test arguments if (( $? = 0 )) ; then # statements to run if test succeed (the command returned RC=0) else # statements to run if the text failed (return RC >0) fiHere test is an external program. Any other program can be used instead of test. After the program was executed the return code of the program is evaluated to decide whether execute then or else branch of if statement.
Like in all programming languages else part is optional. As you understand this "original" notation looks pretty ugly. So it is not surprising that some cosmetics was introduced and instead of test you can use square brackets. This is just syntax sugar, test command is invoked anyway, but it makes scripts less ugly. You can think about "[" as an alias to test (actually in Cygwin this how it is implemented) and "]" as a special form of the comment statement :-)
if [ -f ./machines ] ; then echo "The machines file exists!" else echo "The machines file does not exits exit fiAgain this legacy construct should be never used in your scripts as bash provide with two new, better constructs -- so called double quotes expression -- [[ ...]] and double round brackets conditional expression. So the example above can (and should) be rewritten as
if [[ -f ./machines ]] ; then echo "The machines file exists!" else echo "The machines file does not exits exit fi
Please note that within double square brackets bash will not perform word splitting or pathname expansion, making in most case double quotes unnecessary, if the expression uses variables values of which have a non zero length. The message "The report file ./report.out exists!" is printed only if the file exists. If the file does not exist, the printf command is skipped and execution proceeds after the fi.
NOTES:
This form f if statement, which we called "most primitive form of if statement still have some used. For example:
if cd /fake; then echo "cd returned OK"; fi
If you add an else clause, you get the ability to execute one set of statements if a condition is true or another set of statements if the condition is false. If the status is 0, the condition evaluates to true; if it is anything else, the condition is considered false. The same is true for each condition attached to an elif statement (if any).
For example:if cd /Media/Packages ; then echo "cd returned OK"; else echo "cd failed"; fi
Conditional expressions were not part of the original Borne shell (which was a blunder on the part of its designer even in the situation when memory was tight -- ancient computers that run Unix often have one megabyte (megabyte, not gigabyte) of memory or even less. In original Borne shell conditional expressions were implemented via external command called test which accepts sequence of arguments which are interpreted by this program as expression. As later version of shell (Korn shell) introduced double square brackets and double round brackets expressions which are much better deal, this archaic way should better be forgotten (double square brackets or double round brackets expressions should be used exclusively in you new scrips), but it is preserved for compatibility so we need to know about its existence.
The test command evaluates expression and return the corresponding "return code" -- 0 if expression is true, and non-zero it is false.
Now let's see hot it issued within bash if command, which allow to structure control stream of your scripts into two branches: then branch which is executed if the condition is true and (optional) else branch which is executed, if the conditions false.
The simplest type of flow control construct is the conditional, embodied in the shell if statement, which using Algol-68 syntax and actually is the only survivor of Algol-68 syntax among currently used languages.
You use a conditional when you want to choose whether or not to do something, or to choose among a small number of things to do, according to the truth or falsehood of conditions. Conditions test values of shell variables, characteristics of files, whether or not commands run successfully, and other factors. The shell has a large set of built-in tests that are relevant to the task of shell programming.
There are two major types conditional expressions in bash that we should used exclusively -- doub aqare bracket expression and double round braket expression (see Arithmetic expressions and Comparison operators for more information). All other, legacy types can be safely ignored.
For example:
[[ $user = 'nick' ]] # string comparison condition [[ $user != 'root' ]] # string comparison condition
(( uid == 0 )) (( uid > 1000 ))
(( ( $uid > 10 ) && ( $uid < 100 ) )) # arithmetic condition
Regular expression can also be used in if statement. An expression in bash can be understood as formula that calculates some value. There are several types of expressions in bash. We will mention only three:
Bash simultaneously is a scripting language and a macro processor. So before expression is calculated its content is subjected to several passes of analysis on each of which specific language element are processed (which is called macro expressions). In other languages there is a separate "preprocessor" phase, performed by a separate program. But in bash they are integrated into interpreter. During this process of macroexpansion macrovariables are replaced by their values. Each such action is usually called macrosubstitution or simply substitution. In case of double quoted literals the process of substituting of values of Bash variables into their values is also called interpolation (the term more widely used in Perl then in bash).
Bash performs certain types of macrosubstitution only outside literals(single or double quoted strings and backticked string are called literals) . For example Bash expands tilde to the user home directory only outside any literals
Outside literals after the values of variables and backticked strings were substituted Bash performs two additional operations:
The result is passed to syntax phase of Bash interpreter, where the syntax analyzer try to split script text into statements. If errors are found the process is aborted. After that script is executed one statement at a time.
The order is important and can cause subtle problems in scripts. Suppose you assign a path with a tilde in it in a variable (tile means home directory in Bash):
ls -d ~/bin /home/joeuser/bin
You can see the tilde here work as expected. Now let's enclose the expression ~/bin in double quotes:
$ TEMP="~/bin" $ ls $TEMP ~/bin not found
You can see that this does not work -- tilde substitution double quoted literals not performed as explained above. In double quotes literals tilde symbol is not treated as marcosymbol, representing home directory, but as a regular symbol. that means that within any literal including double quote literals the tilde will remain "as is". In such cases you should use the $HOME variable instead.
The modern form of if construct in bash has the following syntax:
Theif condition then statements [elif condition then statements...] [else statements] fi
elif
or else
parts can be omitted.
You can use as many elif (a contraction of "else if") clauses as you wish; they introduce more conditions, and thus more choices for which set of statements to execute. If you use one or more elifs, you can think of the else clause as the "if all else fails" part.
There are five forms of an IF statement in shell
Shell is the unique language in one more respect: it casts operators into strings or numbers depending of the type of operation used (implicit type conversion). In other owrd operator dictates the type into which the variable is converted before performing a particular opration. This is completely different approach from the most of programming language in which comparison operators are "polymorphic" -- work for all types of operators such as integers, floating point numbers and string. Not so in bash and other shells.
That's why shell uses two set of operators: one for integer comparisons and the other for string comparisons.
That greatly confuse novice programmers, but this idea is not so crazy as you can thing from the first sight. It has its value and is probably one of the possible way to design the language. The only other language that adopted this non-orthodox idea of implicit type conversion based on operators used is Perl. And that create the barrier of entry for Perl too.. This one reason why Python, which is a more traditional language overtook Perl.
This is what is called "Basic language effect" in action -- simpler language what can be quickly learned by novices have much better chances to survive and prosper despite all problems with it design, than a more complex language with less defects in the design, but for example, more convoluted syntax of semantic rules. We see the same effect also with PHP.
So the second way to classify and study conditional expressions is by type they convert the operands. I think that it is the best for learning the intricacies of shell conditional operators and such an approach can provide a useful framework that helps to avoid most Gotchas. It is adopted below. From this point of view in modern shells such as bash we have:
One note about bash: as bash is a derivative of Borne shell, it inherited all the mess that was emanating from it, so in some respect it is even worse then ksh93. The developers has neither clue, no the courage to create a better shell and slide into the easy road of re-implementing all the quirks of Borne shell, plus some.The following three rules (you can call them Softpanorama rules ;-) can help to avoid at least some Gotchas:
Among most annoying Gotchas related to comparison operators one can mention Macrosubstitutions caveats and Quoting caveats. There is also less frequent "Implicit type conversions caveat" when you expect the operand to be numeric, but it is a sting. The later generally should be classified as programming mistakes.
Tips:Historically conditional expressions in Unix shells were introduced via test command. For instance, test can check whether a file is writable before your script tries to write to it. It can treat the string in a shell variable as a number and do comparisons ("Is that number less than 1000?"). You can combine tests, too ("If the file exists and it's readable and the message number is more than 500..."). Some versions of test have more tests than others.
The test command returns a zero status if the test was true and a nonzero status otherwise, so people usually use test with if , while, or until. Here's a way your program could check to see if the user has a readable file named .profile in the home directory:
if test -r $HOME/.profile then echo "$myname: You already have .profile file and its readable" else echo " you do not have .profile file. Copying ..." cp /etc/skel/.profile $HOME/.profile exit 1 fi
The test command also lets you test for something that isn't true. Add an exclamation point (!) before the condition you're testing. For example, the following test is true if the .profile file is not readable:
if test ! -r $HOME/.profile
... ... ...
The hack that was implemented is to link text to the file named [. Yes, that's a left bracket. It was a pretty interesting hack: you can use it interchangeably with the test command with one exception: there has to be a matching right bracket (]) at the end of the test. The second example above could be rewritten this way:
if [ ! -r $HOME/.profile ] then echo "$myname: Can't read your '.profile'. You need to create one and make it readable." 1>&2 exit 1 fi
Be sure to leave space between the brackets and other text. There are a couple of other common gotchas caused by empty arguments because shell attempts macro expansion before syntax analysis.
Again this construct is obsolete and generally should be avoided.
BASH allows you to combine exit statuses logically, so that you can test more than one thing at a time:
In both cases it's useful to think about them as "short-circuit and" and "short-circuit or," respectively:
$ echo $(( 0 && 0 ))
0
$ echo $(( 0 && 1 ))
0
In if statement consists of two conditions (which in turn can be statements ;-) connected by && like in following example
if condition1 && condition2 then ... fi
condition1 is always executed and the result is used to decide if condition 2 should be evaluated. If and only if the first statement returns a return code 0 conditions2 is evaluated (executed). The then clause will be executed only if both succeeded.
In case of short-circuit or the situation is similar:
if statement1 || statement2 then ... fi
statement1 is always executed. If it returns code zero (success), then statement2 will not be executed. Otherwise statement2 will be executed and its return code will be used for the deciding whether to execute then clause of the if statement or else clause. In other words then clause runs either statement1 or statement2 returns a zero code.
true && echo "Yes." Yes. true || echo "No." No false || echo "Yes." Yes.
Note: These constructs can be used outside if statement as well. They provide an elegant way to implement if statement with only else clause.
Let's assume that we need to write a script that checks a /etc/passwd file for the presence of two users who left the company. We can use grep for this: it returns exit status 0 if it found the given string in its input, non-0 if not:
user=$1 if grep $user /etc/passwd || -e $home/$user then print "user $user is not fully removed from the server." fi
Most modern shells implements special construct for numeric conditions called ((...)) construct. See Arithmetic Expressions in BASH. For example
function mess { if (( "$1" > 0 )) ; then total=$1 else total=100 fi tail -$total /var/adm/messages | more }
The shell also provides a older set of arithmetic tests. These are different from character string comparisons like < and >, which compare lexicographic values of strings, not numeric values. For example, "6" is greater than "57" lexicographically, just as "p" is greater than "ox,"
Note: numeric comparisons in double square brackets are obsolete. You should use (( ... )) construct.
Test | Comparison |
---|---|
-lt | Less than |
-le | Less than or equal |
-eq | Equal |
-ge | Greater than or equal |
-gt | Greater than |
-ne | Not equal |
You'll find these to be of the most use in the context of the integer variables we'll see in the next chapter. They're necessary if you want to combine integer tests with other types of tests within the same conditional expression.
However, the shell has a separate syntax for conditional expressions that involve integers only. It's considerably more efficient, so you should use it in preference to the arithmetic test operators listed above. Again, we'll cover the shell's integer conditionals in the next chapter.
In sysadmin scripts often the if statement is used for checking the result of a pipe
no_files=`ls -1 | wc -l` if (( $no_files < $MIN_TESTS )) ; then printf "%s\n" "Too few results...Please check your test suit" exit 192 fi
Please note that the semicolon before the then is required. then is technically a separate command, although it works in conjunction with if . Because they are on one line, the semicolon is needed to separate the commands.
if commands can be nested inside other if commands.
no_files=`ls -1 | wc -l` if (( $no_files < $TOOFEW )) ; then printf "%s\n" "Too few files...but will process them anyway" else if (( $no_files -gt $TOOMANY )) ; then printf "%s\n" "There are many files." else printf "%s\n" "Starting to process the files" fi fi
The commands cannot be cross-nested; the inner if must always be completed before the outer if .
To choose between a series of alternatives, if commands can have an elif part. elif is a shortcut for else if and reduces unnecessary if nesting. The elif part can be followed by a final else part that, if it is present, is executed only when there are no alternatives. Combining these ideas, you can rewrite the previous example as follows.
no_files=`ls -1 | wc -l` if (( "$no_files" < "$TOOFEW" )) ; then printf "%s\n" "Too few files...but will process them anyway" elif (( "$no_files" -gt "$TOOMANY" )) ; then printf "%s\n" "There are many files. Processing may take a long time" else printf "%s\n" "Starting to process the files" fi
The if command doesn't have to be used with the test command. It can run and test the status code of any command.
if rm "$TEMPFILE" ; then printf "%s\n" "$SCRIPT:temp file deleted" else printf "%s - status code %d\n" "$SCRIPT:$LINENO: unable to delete temp file" $? 2>& fi
Embedding complex commands into an if command can make a script difficult to read and debug; you should avoid doing this. In this case, the rm command is not as prominent as it would be if it appeared on a line of its own. Likewise, it is possible to declare variables inside of an if command, but it makes it very difficult to determine which variables exist and which do not.
The [[ ]] construct was introduced in ksh88 as a way to compensate for multiple shortcomings and limitations of the [ ] (test) solution. Essentially it makes [ ] construct obsolete.
The [[ ]] construct expects expression. What is important delimiters [[ and ]] serve as double quotes so you do not have macro expansion inside: tilde substitution and wildcard expansion aren't done within [[ and ]], making quoting less necessary.
One of the [[ ]] construct warts is that it redefined == as a pattern matching operation, which anybody who programmed in C/C++/Java strongly resent. Latest bash version corrected that and allow using Perl-style =~ operator instead (I think ksh93 allow that too), but preserved old "extension" as well :
string="abba" [[ $string =∼ [aeiou] ]] echo $? 0 [[ $string =∼ h[sdfghjkl] ]] echo $? 1
As you see from the examples above [[ ]] construct can be used as a separate statement that returns an exit status depending upon whether condition is true or not. With && and || constructs discussed above this provides an alternative syntax for if-then and if-else constructs
if [[ -d $HOME/$user ]] ; then echo " Home for user $user exists..."; fi
can be written simpler as
[[ -d $HOME/$user ]] && echo " Home for user $user exists..." # shortcut version of if-then construct
There are three types of expressions that can be used inside [[ ... ]] construct:
Numeric comparison. Generally numeric comparisons in double square brackets are obsolete. You should use (( ... )) construct.
Notes:
Operator | True if... |
---|---|
str = pat[5] str == pat[5] |
str matches pat.
Note: that's not what you logically expect, if you have some experience with C /C++/Java programming !!! |
str != pat | str does not match pat. |
str1 < str2 | str1 is less than str2 is collation order used |
str1 > str2 | str1 is greater than str2. |
-n str | str is not null (has length greater than 0). |
-z str | str is null (has length 0). |
file1 -ef file2 | file1 is another name for file2 (hard or symbolic link) |
Several types of comparison are supported:
DAY=`date '+%a'` if [ "$DAY" = "Mon" ] ; then printf "The weekend is over...get to work!\n" fi
The -z (zero length) and -n (not zero length) switches are short forms of = "" and != "", respectively.
If you are used to other computer languages, remember that the quotation marks used in the test command are not only used for string delineation but also for special character handling.
A common use for string comparisons is the testing of shell flag variables. Flags are variables used to indicate whether a particular condition is true. They provide a way to remember previous tests.
Any pair of values can be used to represent the flag's condition, such as true and false or yes and no. However, this can lead to ambiguous conditions when the flag contains an unexpected string such as "NO". Traditionally, if the variable contains anything except a null string, the condition is considered true.
declare -i WEEKEND=0; DAY=`date '+%a'` if [[ "$DAY" = "Sat" || "$DAY" = "Sun" ]] ; then WEEKEND=1 fi
if (( $WEEKEND==1 )); then cores=48 else cores=24 fi
Single tests can be combined together with && (and) and || (or) switches. The test for existence of the generated file in the example above can be rewritten as:
if [[ -f ./machines && -s ./machines ]] ; then echo "$SCRIPT:$LINENO: Machines files was generated correctly" else echo "$SCRIPT:$LINENO: Machine file iether does not exists or have zero length. Aborting execution... " exit 192 fi
The other kind of operator that can be used in conditional expressions checks a file for certain properties. There are approximately two dozens of such operators. Most common are listed below; the rest refer to arcana like sticky bits, sockets, and file descriptors, and thus are of interest only to systems programmers and/or hackers.
Note: ksh88 and Posix shell does not support -e (file exist). For compatibility you can use -f if this is a file
Operator | True if... |
---|---|
-a file | file exists |
-d file | file is a directory |
-f file | file is a regular file (i.e., not a directory or other special type of file) |
-r file | You have read permission on file |
-s file | file exists and is not empty |
-w file | You have write permission on file |
-x file | You have execute permission on file, or directory search permission if it is a directory |
-O file | You own file |
-G file | Your group ID is the same as that of file |
file1 -nt file2 | file1 is newer than file2 |
file1 -ot file2 | file1 is older than file2 |
Before we get to an example, you should know that conditional expressions inside [[ and ]] can also be combined using the logical operators && and ||, just as we saw with plain shell commands above, in the section entitled "Combinations of Exit Statuses."
It's also possible to combine shell commands with conditional expressions using logical operators, like this:
if command && [[ condition ]]; then ...
Note: You can also negate the truth value of a conditional expression by preceding it with an exclamation point (!), so that ! expr evaluates to true only if expr is false.
if [[ ! -d "/root" ]]; then print -n "The directory /root does not exist on the server " fi
Furthermore, you can make complex logical expressions of conditional operators by grouping them with parentheses. construct (statement list) runs the statement list in a subshell, whose exit status is that of the last statement in the list, It can also be used outside if statement.
Now let's write a script that prints essentially the same information as ls -l but in a more user-friendly way. It provides an excellent illustration of many file operations used:
function fileinfo { if [[ ! -a $1 ]]; then print "file $1 does not exist." return 1 # nothing to do fi
if [[ -d $1 ]]; then print -n "$1 is a directory that you may " if [[ ! -x $1 ]]; then print -n "not " fi print "search." elif [[ -f $1 ]]; then print "$1 is a regular file." else print "$1 is a special file." fi if [[ -O $1 ]]; then print 'you own the file.' else print 'you do not own the file.' fi if [[ -r $1 ]]; then print 'you have read permission on the file.' fi if [[ -w $1 ]]; then print 'you have write permission on the file.' fi if [[ -x $1 && ! -d $1 ]]; then print 'you have execute permission on the file.' fi
return 0 }
Here's how this function works:
You can use different type of conditional expression is a single if statement "chained" with && and ||. that allow using ((...)) and [[...]] conditional expression together. For example
if (( $NDS_flag > 0 )) && [[ ! -f /etc/resolv.conf ]] ; then cat /etc/resolv.conf <EOF search example.com local.lan nameserver 127.0.0.1 nameserver 172.16.1.254 EOF fi
The if/then construct tests whether a condition is true, and if so, executes one or more commands. Note that in this context, 0 (zero) will evaluate as true, as will a random string of alphanumeric. Puzzling out the logic of this is left as an exercise for the reader.
Example 1: An interesting usage of ability to execute statements in if construct:
if grep "can't find" <(nslookup sandbox.firma.com) ; then echo "DNS enty for sandbox.firma.com does not exists" fi
Example 2: (adapted from Example 3-9Advanced Bash-Scripting Guide)
What is truth?
#!/bin/bash if [[ 0 ]] #zero then echo "0 is true." else echo "0 is false." fi if [[ ]] #NULL (empty condition) then echo "NULL is true." else echo "NULL is false." fi if [[ "xyz" ]] #string then echo "Random string is true." else echo "Random string is false." fi if [[ $xyz ]] # uninitialized variable then echo "Uninitialized variable is true." else echo "Uninitialized variable is false." fi exit 0
Example 3: Use of ;? to prevent "non-defined variablee" situation
filename=${1:?"filename missing."} howmany=${2:-10} sort -nr $filename | head -$howmany
Or
if [[ -z $1 ]]; then print 'usage: howmany filename [-N]' else filename=$1 howmany=${2:-10} sort -nr $filename | head -$howmany fi
else statement can be avoided if you use exist after detecting the error. Therefore, a more usual style for shell programming is this:
if [[ -z $1 ]]; then print 'usage: howmany filename [-N]' return 1 fi filename=$1 howmany=${2:-10} sort -nr $filename | head -$howmany
From Advanced Bash-Scripting Guide
Example 3-10. Equivalence of [ ] and test
1 #!/bin/bash 2 3 echo 4 5 6 if test -z $1 7 then 8 echo "No command-line arguments." 9 else 10 echo "First command-line argument is $1." 11 fi 12 13 # Both code blocks are functionally identical. 14 15 if [ -z $1 ] 16 # if [ -z $1 17 # also works, but outputs an error message. 18 then 19 echo "No command-line arguments." 20 else 21 echo "First command-line argument is $1." 22 fi 23 24 25 echo 26 27 exit 0
Example 3-11. Tests, command chaining, redirection
1 #!/bin/bash 2 3 # This line is a comment. 4 5 filename=sys.log 6 7 if [ ! -f $filename ] 8 then 9 touch $filename; echo "Creating file." 10 else 11 cat /dev/null > $filename; echo "Cleaning out file." 12 fi 13 14 # Of course, /var/log/messages must have 15 # world read permission (644) for this to work. 16 tail /var/log/messages > $filename 17 echo "$filename contains tail end of system log." 18 19 exit 0
Example 3-12. arithmetic and string comparisons
1 #!/bin/bash 2 3 a=4 4 b=5 5 6 # Here a and b can be treated either as integers or strings. 7 # There is some blurring between the arithmetic and integer comparisons. 8 # Be careful. 9 10 if [ $a -ne $b ] 11 then 12 echo "$a is not equal to $b" 13 echo "(arithmetic comparison)" 14 fi 15 16 echo 17 18 if [ $a != $b ] 19 then 20 echo "$a is not equal to $b." 21 echo "(string comparison)" 22 fi 23 24 echo 25 26 exit 0
Example 3-13. testing whether a string is null
1 #!/bin/bash 2 3 # If a string has not been initialized, it has no defined value. 4 # This state is called "null" (not the same as zero). 5 6 7 if [ -n $string1 ] # $string1 has not been declared or initialized. 8 then 9 echo "String \"string1\" is not null." 10 else 11 echo "String \"string1\" is null." 12 fi 13 # Wrong result. 14 # Shows $string1 as not null, although it was not initialized. 15 16 echo 17 18 # Lets try it again. 19 20 if [ -n "$string1" ] # This time, $string1 is quoted. 21 then 22 echo "String \"string1\" is not null." 23 else 24 echo "String \"string1\" is null." 25 fi 26 27 echo 28 29 if [ $string1 ] # This time, $string1 stands naked. 30 then 31 echo "String \"string1\" is not null." 32 else 33 echo "String \"string1\" is null." 34 fi 35 # This works fine. 36 # The [ ] test operator alone detects whether the string is null. 37 38 echo 39 40 string1=initialized 41 42 if [ $string1 ] # This time, $string1 stands naked. 43 then 44 echo "String \"string1\" is not null." 45 else 46 echo "String \"string1\" is null." 47 fi 48 # Again, gives correct result. 49 50 51 exit 0 52 53 # Thanks to Florian Wisser for pointing this out.
Example 3-14. zmost
1 #!/bin/bash 2 3 #View gzipped files with 'most' 4 5 NOARGS=1 6 7 if [ $# = 0 ] 8 # same effect as: if [ -z $1 ] 9 then 10 echo "Usage: `basename $0` filename" >&2 11 # Error message to stderr. 12 exit $NOARGS 13 # Returns 1 as exit status of script 14 # (error code) 15 fi 16 17 filename=$1 18 19 if [ ! -f $filename ] 20 then 21 echo "File $filename not found!" >&2 22 # Error message to stderr. 23 exit 2 24 fi 25 26 if [ ${filename##*.} != "gz" ] 27 # Using bracket in variable substitution. 28 then 29 echo "File $1 is not a gzipped file!" 30 exit 3 31 fi 32 33 zcat $1 | most 34 35 exit 0 36 37 # Uses the file viewer 'most' 38 # (similar to 'less')
|
Switchboard | ||||
Latest | |||||
Past week | |||||
Past month |
To add in your Bash configuration files:
# These lines will print a message if the noclobber option is set: if [ -o noclobber ] then echo "Your files are protected against accidental overwriting using redirection." fi
|
Switchboard | ||||
Latest | |||||
Past week | |||||
Past month |
Google matched content |
- -a
- logical and
exp1 -a exp2 returns true if both exp1 and exp2 are true.
- -o
- logical or
exp1 -o exp2 returns true if either exp1 or exp2 are true.
These are simpler forms of the comparison operators && and ||, which require brackets to separate the target expressions.
In bash we have extended set of file test operators:
- -e
- file exists
- -f
- file is a regular file
- -s
- file is not zero size
- -d
- file is a directory
- -b
- file is a block device (floppy, cdrom, etc.)
- -c
- file is a character device (keyboard, modem, sound card, etc.)
- -p
- file is a pipe
- -L
- file is a symbolic link
- -S
- file is a socket
- -r
- file is readable (has read permission)
- -w
- file has write permission
- -x
- file has execute permission
- -g
- group-id flag set on file
- -u
- user-id flag set on file
- -k
- "sticky bit" set (if user does not own a directory that has the sticky bit set, she cannot delete files in it, not even files she owns)
- -O
- you are owner of file
- -G
- group-id of file same as yours
- -t n
- file descriptor n is open
This usually refers to stdin, stdout, and stderr (file descriptors 0 - 2).
- f1 -nt f2
- file f1 is newer than f2
- f1 -ot f2
- file f1 is older than f2
- f1 -ef f2
- files f1 and f2 are links to the same file
- !
- "not" -- reverses the sense of the tests above (returns true if condition absent).
- -eq
- is equal to ($a -eq $b)
- -ne
- is not equal to ($a -ne $b)
- -gt
- is greater than ($a -gt $b)
- -ge
- is greater than or equal to ($a -ge $b)
- -lt
- is less than ($a -lt $b)
- -le
- is less than or equal to ($a -le $b)
- =
- is equal to ($a = $b)
- !=
- is not equal to ($a != $b)
- \<
- is less than, in ASCII alphabetical order ($a \< $b)
Note that the "<" needs to be escaped.
- \>
- is greater than, in ASCII alphabetical order ($a \> $b)
Note that the ">" needs to be escaped.
See Example 3-91 for an application of this comparison operator.
- -z
- string is "null", that is, has zero length
- -n
- string is not "null".
This test requires that the string be quoted within the test brackets. You may use ! -z instead, or even just the string itself, without a test operator (see Example 3-13).
Society
Groupthink : Two Party System as Polyarchy : Corruption of Regulators : Bureaucracies : Understanding Micromanagers and Control Freaks : Toxic Managers : Harvard Mafia : Diplomatic Communication : Surviving a Bad Performance Review : Insufficient Retirement Funds as Immanent Problem of Neoliberal Regime : PseudoScience : Who Rules America : Neoliberalism : The Iron Law of Oligarchy : Libertarian Philosophy
Quotes
War and Peace : Skeptical Finance : John Kenneth Galbraith :Talleyrand : Oscar Wilde : Otto Von Bismarck : Keynes : George Carlin : Skeptics : Propaganda : SE quotes : Language Design and Programming Quotes : Random IT-related quotes : Somerset Maugham : Marcus Aurelius : Kurt Vonnegut : Eric Hoffer : Winston Churchill : Napoleon Bonaparte : Ambrose Bierce : Bernard Shaw : Mark Twain Quotes
Bulletin:
Vol 25, No.12 (December, 2013) Rational Fools vs. Efficient Crooks The efficient markets hypothesis : Political Skeptic Bulletin, 2013 : Unemployment Bulletin, 2010 : Vol 23, No.10 (October, 2011) An observation about corporate security departments : Slightly Skeptical Euromaydan Chronicles, June 2014 : Greenspan legacy bulletin, 2008 : Vol 25, No.10 (October, 2013) Cryptolocker Trojan (Win32/Crilock.A) : Vol 25, No.08 (August, 2013) Cloud providers as intelligence collection hubs : Financial Humor Bulletin, 2010 : Inequality Bulletin, 2009 : Financial Humor Bulletin, 2008 : Copyleft Problems Bulletin, 2004 : Financial Humor Bulletin, 2011 : Energy Bulletin, 2010 : Malware Protection Bulletin, 2010 : Vol 26, No.1 (January, 2013) Object-Oriented Cult : Political Skeptic Bulletin, 2011 : Vol 23, No.11 (November, 2011) Softpanorama classification of sysadmin horror stories : Vol 25, No.05 (May, 2013) Corporate bullshit as a communication method : Vol 25, No.06 (June, 2013) A Note on the Relationship of Brooks Law and Conway Law
History:
Fifty glorious years (1950-2000): the triumph of the US computer engineering : Donald Knuth : TAoCP and its Influence of Computer Science : Richard Stallman : Linus Torvalds : Larry Wall : John K. Ousterhout : CTSS : Multix OS Unix History : Unix shell history : VI editor : History of pipes concept : Solaris : MS DOS : Programming Languages History : PL/1 : Simula 67 : C : History of GCC development : Scripting Languages : Perl history : OS History : Mail : DNS : SSH : CPU Instruction Sets : SPARC systems 1987-2006 : Norton Commander : Norton Utilities : Norton Ghost : Frontpage history : Malware Defense History : GNU Screen : OSS early history
Classic books:
The Peter Principle : Parkinson Law : 1984 : The Mythical Man-Month : How to Solve It by George Polya : The Art of Computer Programming : The Elements of Programming Style : The Unix Haters Handbook : The Jargon file : The True Believer : Programming Pearls : The Good Soldier Svejk : The Power Elite
Most popular humor pages:
Manifest of the Softpanorama IT Slacker Society : Ten Commandments of the IT Slackers Society : Computer Humor Collection : BSD Logo Story : The Cuckoo's Egg : IT Slang : C++ Humor : ARE YOU A BBS ADDICT? : The Perl Purity Test : Object oriented programmers of all nations : Financial Humor : Financial Humor Bulletin, 2008 : Financial Humor Bulletin, 2010 : The Most Comprehensive Collection of Editor-related Humor : Programming Language Humor : Goldman Sachs related humor : Greenspan humor : C Humor : Scripting Humor : Real Programmers Humor : Web Humor : GPL-related Humor : OFM Humor : Politically Incorrect Humor : IDS Humor : "Linux Sucks" Humor : Russian Musical Humor : Best Russian Programmer Humor : Microsoft plans to buy Catholic Church : Richard Stallman Related Humor : Admin Humor : Perl-related Humor : Linus Torvalds Related humor : PseudoScience Related Humor : Networking Humor : Shell Humor : Financial Humor Bulletin, 2011 : Financial Humor Bulletin, 2012 : Financial Humor Bulletin, 2013 : Java Humor : Software Engineering Humor : Sun Solaris Related Humor : Education Humor : IBM Humor : Assembler-related Humor : VIM Humor : Computer Viruses Humor : Bright tomorrow is rescheduled to a day after tomorrow : Classic Computer Humor
The Last but not Least Technology is dominated by two types of people: those who understand what they do not manage and those who manage what they do not understand ~Archibald Putt. Ph.D
Copyright © 1996-2021 by Softpanorama Society. www.softpanorama.org was initially created as a service to the (now defunct) UN Sustainable Development Networking Programme (SDNP) without any remuneration. This document is an industrial compilation designed and created exclusively for educational use and is distributed under the Softpanorama Content License. Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine.
FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available to advance understanding of computer science, IT technology, economic, scientific, and social issues. We believe this constitutes a 'fair use' of any such copyrighted material as provided by section 107 of the US Copyright Law according to which such material can be distributed without profit exclusively for research and educational purposes.
This is a Spartan WHYFF (We Help You For Free) site written by people for whom English is not a native language. Grammar and spelling errors should be expected. The site contain some broken links as it develops like a living tree...
|
You can use PayPal to to buy a cup of coffee for authors of this site |
Disclaimer:
The statements, views and opinions presented on this web page are those of the author (or referenced source) and are not endorsed by, nor do they necessarily reflect, the opinions of the Softpanorama society. We do not warrant the correctness of the information provided or its fitness for any purpose. The site uses AdSense so you need to be aware of Google privacy policy. You you do not want to be tracked by Google please disable Javascript for this site. This site is perfectly usable without Javascript.
Last modified: February 10, 2021