Bash

From Partyvan Wiki

Jump to: navigation, search

Bash is a shell that can be run on most UNIX derived systems, including Linux and MAC OS X

Contents

Features

Auto completion

Start typing and hit <tab> to make bash complete your input. If your input leads to ambiguous completions, you might have to hit <tab> a second time to see all recommendations.

Example:

You want to edit a text file called "Loldongs" with vi, the text editor. So you type

vi Loldongs

But if Loldongs is the only file in the folder you can simply do the following:

vi L<tab>

And bash will complete the rest.


Now let's say you want to open a file called "Dickbutt" with vi, but there's another file in the folder called "Dickhole". If you type

vi Dick<tab>

The system will not autocomplete the input because there is an ambiguity. The motherboard speaker will emit a beep (However this could not happen), and you can press <Tab> again so bash can show which names were in conflict. In this case the system will output "Dickbutt" and "Dickhole". By typing

vi Dickb<tab>

The system will be able to successfully complete the input with "Dickbutt"

Input/output forwarding/redirecting

Every input or output produced by a program invoked in the bash shell can be redirected to a file, another program or a different data stream.

Pipes are used to forward the output of one program to the input of another program.

Syntax:

prog1 | prog2

Output redirection is used to redirect the output of a program to a file. It can be used in 2 different ways: Overwrite (truncate) and append.

Syntax for overwriting:

some_prog > some_file

Syntax for appending:

some_prog >> some_file

The output of *NIX programs (generally) goes to two separated output streams: Standard output (stdout) and standard error (stderr). Therefor output redirecting also works for those separated streams. To make it easier to type, the streams are enumerated: stdout is 1, stderr is 2. The default way of output redirecting shown above redirects only stdout and could also be written

some_prog 1> some_file

or

some_prog 1>> some_file

To redirect the stderr stream to a file, use

some_prog 2> some_file

or

some_prog 2>> some_file

The two methods can be combined, this can be useful for error logging:

some_prog 1> output_file 2> error_logfile

To redirect both streams to one file, use

some_prog &> some_file

Input redirection is used to redirect the content of a file to the input of a program. This enables you to process files with programs that usually only accept direct input.

Syntax:

some_prog < some_file

You can disregard output by redirecting it to /dev/null, like this:

cat file1 > dev/null 2>&1

What does the above command do? In order to properly understand it could be better if you read both section from right to left. The last one redirects 2 (Which is stderr) to 1 (stdout). The first command tells to use the command "cat" on the file "file1" and then send the output to /dev/null. All data sent to /dev/null will be disregarded and gone forever. (Note: /dev/null is not the equivalent of the Windows' Recycle Bin; the information will not stay there, it will simply fall into a pit of unretrievable void. Any attempt to read the contents of /dev/null will simply result on an end-of-file response)

Variables

Variables are used to store pieces of information and associate them with a name to access them.

Declaring variables can be done in 2 different ways.

The simple way:

my_variable='my valuable piece of information'

Make sure that there is no space between the variable name and the equal sign. otherwise it won't work.

The elaborate way comes along with the Usage of the bash built-in command 'declare' which enables you to declare variables with specific attributes, for example to make them read-only. Use 'help declare' for further information.

Reading the content of variables is done by putting the dollar sign in front of the variable:

$my_variable

To use a variable inside a string, you have to put the string in double quotes. In single quotes the special meaning of the dollar sign isn't interpreted by bash. The following examples will used the variable we declared above.

"My string contains $my_variable"

will result to 'My string contains my valuable piece of information', while

'My string contains $my_variable'

will result to 'My string contains $my_variable'

To make sure the variable's content is recognized as one piece (Some programs you can pass your variables to, might get terrible hiccups if the content contains spaces and/or tabs), use curly brackets around the variable name (the whole thing still has to be preceded by the dollar sign):

${my_variable}

Sub-shells

Bash can also start sub-shells, that are other instances of bash that are running inside the currently open bash to execute a set of commands. To execute some commands in a sub-shell, enclose them in brackets and put a dollar sign in front:

$( some fancy commands in a sub-shell )

This is useful to assign the output of commands to a variable:

my_variable=$( some commands in a sub-shell producing some output )

In sub-shells bash can also do simple calculations, just enclose the term you want to calculate in two pairs of brackets and put a dollar sign in front:

$(( 9000+1 ))	# It's over 9000!
$(( 101/0 ))	# Dividing by zero works, too!? Oh shi--

Logical Expressions

Bash can evaluate logical expressions. In *NIX based systems, the two states of Boolean logic, True and False are represented by Numbers: 0 stands for True, any other number for False. There also exist two little helper applications which have no other purpose than providing True or False:

true
false

They issue their value as return code (see next section)

Return codes

Return codes are pieces of information returned by a program to the Operating System before it ends, usually a number. On *NIX based systems Programs use the definition of True and False as 0 and non-zero to indicate, if their run was successful. If they ran successfully, they return the number 0, if there was an error, any other number is returned. So we can use the return codes of programs for logical evaluation. The return code of a program can be accessed by a variable (until the next program is run, which overwrites it with it's own return code)

$?

To make use of return codes in a bash script, you can use the keyword 'return'. This also ends the current script.

Example for successful return:

return 0

Example for unsuccessful return:

return 9001

Boolean operators

AND

Returns True (0), if both the left hand and the right hand expression return True.

expression1 && expression2

OR

Returns True, if either the left hand or the right hand expression return True.

expression1 || expression2

NOT

Inverts the value of the following expression.

! expression

Comparison

Comparisons and tests can be done with the helper application 'test'. It for example provides the comparison operators '=', '!=', '>', and '<', but also much more like checking if a file exists, or is of a special type. To learn about the full capablities of test, simply type

help test

Example for simple comparison:

test 7 = 9001

Test can be abbreviated by embedding the statement in square brackets (spaces between bracket and expression are necessary):

[ 7 = 9001 ]

Conditional statements

To make use of all the logic we had above, we need to be able to to make decisions based on them. That's what Bash's conditional statements (if, else) are for. Since every good *NIX program makes use of return codes to indicate it's success, we can use every program as source of logic to make conditional statements.

If

the if statement evaluates an expression and runs a series of commands, if the expression is true. Every if/else statement is closed by the keyword 'fi' ('if' backwards)

if expression; then command1; command2; command_over9000; fi

if you don't like long lines, you can also type this like the following example (indenting not required, it's only to make the code more readable)

if expression
then
     command1
     command2
     command_over9000
fi

Else

To have an alternative set of commands executed, if the condition is false, Bash provides the else statement.

if expression; then some; commands; else some; other; commands; fi

or in multiple lines:

if expression
then
     some
     commands
else
     some
     other
     commands
fi

Else If

The else if statement is provided by the keyword 'elif'

if expression1; then some; commands; elif expression2; then some; other; commands; fi;

or better readable:

if expression1
then
     some
     commands
elif expression2
then
     some
     other
     commands
fi

of course the elif statement can be followed by an else or another elif:

if expression1
then
     command1
elif expression2
then
     command2
else
     command3
fi

Line Endings

Usually a new line makes bash execute the typed line (except this line continues an unfinished statement)

To avoid Bash execute at end of line, just put a backslash as last character in this line. Bash now will now consider the current and the following line as one long line:

some code that is very loooooooooooooong

equals to

some code that is \
very loooooooooooooong

You can also put multiple lines into one. Simply put a semicolon (';') at the place where ususually the new line would start:

some
code 
that
could
also
fit
in
one
line

equals to

some; code; that; could; also; fit; in; one; line

(the whitespace is not strictly necessary, but makes it a lot more readable)

Scripting

Basically a script is nothing else than regular shell commands written to a file, so you don't have to type them over and over again.

Comments

Everything preceded by a '#' is a comment which is completely ignored by bash (You can still use '#' within strings, since the quotes discard it's special meaning). Comments can and should be used in scripts to explain complicated code with a not very obvious purpose. (You don't only do this for others, but also for yourself. Half a year after coding some piece of shit you'll be happy, if you commented properly)

# This is a comment
some_code	# This is a comment, too
some_code '# this is not a comment' "# this neither." # "but this is one"

A very handy use of comments is to temporarily disable parts of code for testing/searching errors. A special comment is the 'Shebang'. It is put into the first line of a script file to tell the operating system which program it should use to run the script. It consits of the '#' followed by an exclamation point and the path to the program that should be used to run the script. For bash scripts this would usually be

#!/bin/bash

Examples

The following examples might help you improve your bash skills. To try them, simply copy and paste them a bash shell, or paste them to a file, then make the file executable by running

chmod +x path/to/file

After that you can run the script by typing the path to it in the shell. To make it easier to call your awesome script, you can put it into a directory which is in bash's search path, then you can call your script by it's filename only. (For user created scripts /usr/local/bin/ is a suitable place)

THE GAME

Always know if you just lost it, or if you're still in your 30 minutes period of immunity. Save to 'thegame', make executable and run every time you suspect you just lost THE GAME. Then the script will keep track of the last time you lost it to make sure you can enjoy all your 30 minutes of immunity.

#!/bin/bash
 
CONFIG="${HOME}/.thegamerc"	# Config file to store last time of losing
 
# Explicitly declare variables needed for time calculation as integers, to
# make sure they're not accidentally interpreted as strings
declare -i LAST_TIME_LOST
declare -i NOW=$(date +%s)	# Now, a UNIX timestamp of the current time
declare -i TOLERANCE=1800	# Tolerance for not losing: 30 minutes
 
echo 'THE GAME.'
 
# Try to read last time of playing from config. Else default to 0 (UNIX time)
if [ -e  ${CONFIG} ]
then
	# Read only the first line of the config file,
	# since there should be no more lines.
	LAST_TIME_LOST=$(head -n 1 ${CONFIG})
else
	LAST_TIME_LOST=0
fi
 
# PLAY!
if [ $((${LAST_TIME_LOST}+${TOLERANCE})) -lt ${NOW} ]
then
	# If last time plus tolerance are before (lesser than) now, you lost.
	echo 'You just lost it.'
	# To make sure you can enjoy your 30 minutes of immunity,
	# the timestamp of now is stored to the config file
	echo ${NOW} > ${CONFIG}
else
	DIFFERENCE=$(( ${LAST_TIME_LOST}+${TOLERANCE}-${NOW} ))
	echo "Time remaining until you lose again: ${DIFFERENCE} seconds"
fi
 
# We are a polite game :P
echo 'Thank you for playing!'
Personal tools
Invasion Boards