Bash by Examples - LinuxIntro
-
Upload
laith-mustafa-al-obaidy -
Category
Documents
-
view
238 -
download
0
Transcript of Bash by Examples - LinuxIntro
-
7/21/2019 Bash by Examples - LinuxIntro
1/14
4/27/15, 3:10 PaBE - Bash By Examples - LinuxIntro
Page 1 otp://www.linuxintro.org/wiki/BaBE
MindMap
BaBE - Bash By ExamplesFrom Li nuxIntroRedirec ted from BaBE)
BaBE - Bash By Exampl es; Your signicant Linux scripting tutorial;;
Content s
1 Hello world2 calli ng commands3 variables
3.1 input
3.2 ${}3.3 com monmistakes
4 parameter s5 return codes6 line feed s7 storing a c ommand'soutput
7.1 $()7.2 backticks7.3 pip ing
7.4 compar ison7.5 co mmonmistakes
8 conditions8.1 empty strings8.2 arithmeticexpressions8.3 not equal8.4 commonmistakes
9 Redirections10 lling les11 loops
11.1 for loops11.2 while loops
12 negations13 sending a process tothe background14 forking a process
http://www.linuxintro.org/wiki/BaBE#sending_a_process_to_the_backgroundhttp://www.linuxintro.org/wiki/BaBE#sending_a_process_to_the_backgroundhttp://www.linuxintro.org/wiki/BaBE#for_loopshttp://www.linuxintro.org/wiki/BaBE#common_mistakes_3http://www.linuxintro.org/wiki/BaBE#arithmetic_expressionshttp://www.linuxintro.org/wiki/BaBE#empty_stringshttp://www.linuxintro.org/wiki/BaBE#conditionshttp://www.linuxintro.org/wiki/BaBE#common_mistakes_2http://www.linuxintro.org/wiki/BaBE#comparisonhttp://www.linuxintro.org/wiki/BaBE#pipinghttp://www.linuxintro.org/wiki/BaBE#backtickshttp://www.linuxintro.org/wiki/BaBE#.24.28.29http://www.linuxintro.org/wiki/BaBE#storing_a_command.27s_outputhttp://www.linuxintro.org/wiki/BaBE#line_feedshttp://www.linuxintro.org/wiki/BaBE#return_codeshttp://www.linuxintro.org/wiki/BaBE#parametershttp://www.linuxintro.org/wiki/BaBE#common_mistakeshttp://www.linuxintro.org/wiki/BaBE#.24.7B.7Dhttp://www.linuxintro.org/wiki/BaBE#inputhttp://www.linuxintro.org/wiki/BaBE#variableshttp://www.linuxintro.org/wiki/BaBE#calling_commandshttp://www.linuxintro.org/wiki/BaBE#Hello_worldhttp://www.linuxintro.org/index.php?title=BaBE&redirect=nohttp://www.linuxintro.org/wiki/BaBE#forking_a_processhttp://www.linuxintro.org/wiki/BaBE#sending_a_process_to_the_backgroundhttp://www.linuxintro.org/wiki/BaBE#negationshttp://www.linuxintro.org/wiki/BaBE#while_loopshttp://www.linuxintro.org/wiki/BaBE#for_loopshttp://www.linuxintro.org/wiki/BaBE#loopshttp://www.linuxintro.org/wiki/BaBE#filling_fileshttp://www.linuxintro.org/wiki/BaBE#Redirectionshttp://www.linuxintro.org/wiki/BaBE#common_mistakes_3http://www.linuxintro.org/wiki/BaBE#not_equalhttp://www.linuxintro.org/wiki/BaBE#arithmetic_expressionshttp://www.linuxintro.org/wiki/BaBE#empty_stringshttp://www.linuxintro.org/wiki/BaBE#conditionshttp://www.linuxintro.org/wiki/BaBE#common_mistakes_2http://www.linuxintro.org/wiki/BaBE#comparisonhttp://www.linuxintro.org/wiki/BaBE#pipinghttp://www.linuxintro.org/wiki/BaBE#backtickshttp://www.linuxintro.org/wiki/BaBE#.24.28.29http://www.linuxintro.org/wiki/BaBE#storing_a_command.27s_outputhttp://www.linuxintro.org/wiki/BaBE#line_feedshttp://www.linuxintro.org/wiki/BaBE#return_codeshttp://www.linuxintro.org/wiki/BaBE#parametershttp://www.linuxintro.org/wiki/BaBE#common_mistakeshttp://www.linuxintro.org/wiki/BaBE#.24.7B.7Dhttp://www.linuxintro.org/wiki/BaBE#inputhttp://www.linuxintro.org/wiki/BaBE#variableshttp://www.linuxintro.org/wiki/BaBE#calling_commandshttp://www.linuxintro.org/wiki/BaBE#Hello_worldhttp://www.linuxintro.org/index.php?title=BaBE&redirect=no -
7/21/2019 Bash by Examples - LinuxIntro
2/14
4/27/15, 3:10 PaBE - Bash By Examples - LinuxIntro
Page 2 otp://www.linuxintro.org/wiki/BaBE
15 functions16 react on CTRL_C17 helpful programs
17.1 awk: read aspecic column17.2 grep: search astring
17.3 sed: replace astring17.4 tr: replacelinebreaks17.5 wc: count17.6 dialog: createdialogs
18 See also
Hello worldThe easiest way to get your feet wet with a programming language is to start with a program that simply outputs
trivial text, the so-called hello-world-example. Here it is for bash:
create a le named hello in your home directory with the following content:
#!/bin/bash (http://en.wikipedia.org/wiki/Shebang_%28Unix%29)cho "Hello, world!"
open a console, enter
dhmod +x hello
now you can execute your le like this:
# ./helloHello, world!
or like this:
# bash helloHello, world!
You see - the output of your shell program is the same as if you had entered the commands into a console.
http://www.linuxintro.org/wiki/Programhttp://www.linuxintro.org/wiki/Open_a_consolehttp://www.linuxintro.org/wiki/Echohttp://en.wikipedia.org/wiki/Shebang_%28Unix%29http://www.linuxintro.org/wiki/BaBE#See_alsohttp://www.linuxintro.org/wiki/BaBE#dialog:_create_dialogshttp://www.linuxintro.org/wiki/BaBE#wc:_counthttp://www.linuxintro.org/wiki/BaBE#tr:_replace_linebreakshttp://www.linuxintro.org/wiki/BaBE#sed:_replace_a_stringhttp://www.linuxintro.org/wiki/BaBE#grep:_search_a_stringhttp://www.linuxintro.org/wiki/BaBE#awk:_read_a_specific_columnhttp://www.linuxintro.org/wiki/BaBE#helpful_programshttp://www.linuxintro.org/wiki/BaBE#react_on_CTRL_Chttp://www.linuxintro.org/wiki/BaBE#functions -
7/21/2019 Bash by Examples - LinuxIntro
3/14
4/27/15, 3:10 PaBE - Bash By Examples - LinuxIntro
Page 3 otp://www.linuxintro.org/wiki/BaBE
calling commandsn your shell script you can call every command that you can call when opening a console:
cho "This is a directory listing, latest modified files at the bottom:"s -ltr
cho "Now calling a browser"irefoxcho "Continuing with the script"
variables
nput
To show you how to deal with variables, we will now write a script that asks for your name and greets you:
cho "what is your name? "ead namecho "hello $name"
You see that the name is stored in a variable $name. Note the quotation marks " around "hello $name". By usinhese you say that you want variables to be replaced by their content. If you were to use apostrophes, the name
would not be printed, but $name instead.
${}The ${} operator stands for the variable, there is no difference if you write
cho "$name"
or
cho "${name}"
So what is the sense of this? Imagine you want to echo a string directly, without any blank, after the content of avariable:
cho "if I add the syllable owa to your name it will be ${name}owa"
common mistakes
http://www.linuxintro.org/wiki/Opening_a_console -
7/21/2019 Bash by Examples - LinuxIntro
4/14
4/27/15, 3:10 PaBE - Bash By Examples - LinuxIntro
Page 4 otp://www.linuxintro.org/wiki/BaBE
Note that the variable is called $name, however the correct statement to read it from the keyboard is
ead name
t is a common mistake to write
ead $name
which means "read a string and store it into the variable whose name is stored in $name"
parameters
cho "Here are all parameters you called this script with: $@"cho "Here is parameter 1: $1"cho "Which parameter do you want to be shown? "
ead numberrgs=("$@")cho "${args[$number-1]}"
return codesEvery bash script can communicate with the rest of the system by
sending data to stdout
sending data to stderrdelivering a return code
The return code is 0 if everything worked well. You can query it for the most recent command using $?:
ootstick@bootstick:~$ echo "hello world"; echo $?hello world
ootstick@bootstick:~$ echo "hello world">/proc/cmdline; echo $?ash: /proc/cmdline: Permission denied
n bash, true is 0 and false is any value but 0. There exist two commands, true and false that deliver true or false,espectively:
ootstick@bootstick:~$ true; echo $?
ootstick@bootstick:~$ false; echo $?
http://www.linuxintro.org/wiki/Stderrhttp://www.linuxintro.org/wiki/Stdout -
7/21/2019 Bash by Examples - LinuxIntro
5/14
4/27/15, 3:10 PaBE - Bash By Examples - LinuxIntro
Page 5 otp://www.linuxintro.org/wiki/BaBE
line feedsLet's look at the following script:
ead namef [ $name = "Thorsten" ]; then echo "I know you"; fi
nstead of a semicolon you can write a line feed like this:
ead namef [ $name = "Thorsten" ]
then echo "I know you"i
And instead of a line feed you can use a semicolon:
ead name; if [ $name = "Thorsten" ]; then echo "I know you"; fi
f you want to insert a line feed where you do not need one, e.g. to make the code better readable, you mustprepend it with a backslash:
ead \name
f [ $name = "Thorsten" ]then \
echo "I know you"i
storing a command's outputTo read a command's output into a variable use $(), backticks or piping.
$()
rch=$(uname -m)cho "Your system is a $arch system."
backticks
rch=`uname -m`cho "Your system is a $arch system."
http://www.linuxintro.org/wiki/Piping -
7/21/2019 Bash by Examples - LinuxIntro
6/14
4/27/15, 3:10 PaBE - Bash By Examples - LinuxIntro
Page 6 otp://www.linuxintro.org/wiki/BaBE
piping
uname -m | while read arch; do echo "Your system is a $arch system."; done
comparison
The advantage of using backticks over $() is that backticks also work in the sh shell. The advantage of using $()over backticks is that you can cascade them. In the example below we use this possibility to get a list of all lesnstalled with rpm on the system:
ilelist=$(rpm -ql $(rpm -qa))
You can use the piping approach if you need to cascade in sh, but this is not focus of this bash tutorial.
common mistakesUsually unexperienced programmers try something like
uname -m | read arch
which does not work (http://mywiki.wooledge.org/BashFAQ/024) . You must embed the read into a while loop.
conditionsThe easiest form of a condition in bash is this if example:
cho "what is your name? "ead namef [ $name = "Thorsten" ]; then echo "I know you"; fi
Now let's look closer at this, why does it work? Why is there a blank needed behind the [ sign? The answer ishat [ is just an ordinary command in the shell. It delivers a return code for the expression that follows till the ]
ign. To prove this we can write a script:
f true; then echo "the command following if true is being executed"; fif false; then echo "this will not be shown"; fi
empty strings
http://www.linuxintro.org/wiki/Commandhttp://mywiki.wooledge.org/BashFAQ/024http://www.linuxintro.org/wiki/Rpm -
7/21/2019 Bash by Examples - LinuxIntro
7/14
4/27/15, 3:10 PaBE - Bash By Examples - LinuxIntro
Page 7 otp://www.linuxintro.org/wiki/BaBE
An empty string evaluates to false inside the [ ] operators so it is possible to check if a string result is empty likhis:
weedleburg:~ # result=weedleburg:~ # if [ $result ]; then echo success; fiweedleburg:~ # result=goodweedleburg:~ # if [ $result ]; then echo success; fiuccess
arithmetic expressions
cho "what is your age? "ead agef (( $age >= 21 )); then echo "Let's talk about sex."; fi
not equal
To check if a variable is NOT equal to whatever, use !=:
f [ "$LANG" != "C" ]; then echo "please set your system lanugage to C"; fi
common mistakes
Common mistakes are:
to forget the blank behind/before the [ or ] characterto forget the blank behind/before the equal signsee what does "unary operator expected" mean
RedirectionsTo redirect the output of a command to a le you have to consider that there are two output streams in UNIX,tdout and stderr.
lling lesTo create a le, probably the easiest way is to use cat. The following example writes text into README till aine occurs that only contains the string "EOF":
at >README
-
7/21/2019 Bash by Examples - LinuxIntro
8/14
4/27/15, 3:10 PaBE - Bash By Examples - LinuxIntro
Page 8 otp://www.linuxintro.org/wiki/BaBE
This is line 2This is the last lineEOF
Afterwards, README will contain the 3 lines below the cat command and above the line with EOF.
loopsfor loops
Here is an example for a for-loop. It makes a backup of all text les:
or i in *.txt; do cp $i $i.bak; done
The above command takes each .txt le in the current directory, stores it in the variable $i and copies it to $i.bak.
So le.txt gets copied to le.txt.bat.
You can also use subsequent numbers as a for loop using the command seq like this:
or i in $(seq 1 1 3); do echo $i; done
while loops
while true; do read line; done
negationsYou can negate a result with the ! operator. $? is the last command's return code:
# true# echo $?
# false
# echo $?
# ! true# echo $?
# ! false# echo $?
So you get an endless loop out of:
http://www.linuxintro.org/wiki/Echohttp://www.linuxintro.org/wiki/Seqhttp://www.linuxintro.org/wiki/Variablehttp://www.linuxintro.org/wiki/Cphttp://www.linuxintro.org/wiki/Backup -
7/21/2019 Bash by Examples - LinuxIntro
9/14
4/27/15, 3:10 PaBE - Bash By Examples - LinuxIntro
Page 9 otp://www.linuxintro.org/wiki/BaBE
hile ! false; do echo hallo; done
The following code checks the le /tmp/success to contain "success". As long as this is not the case it continuehecking:
hile ! (grep "success" /tmp/success)
dosleep 30done
The following code checks if the le dblog.log exists. As long as this is not the case it tries to download it via ftp:
hile ! (test -e dblog.log); doftp -p ftp://user:password@server/tmp/dblog.log >/dev/nullecho -en "."sleep 1
done
sending a process to the backgroundTo send a process to the background, use the ampersand sign (&):
irefox & echo "Firefox has been started"
You see a newline is not needed after the &
forking a processYou can build a process chain using parantheses. This is useful if you want to have two instruction streams beingxecuted in parallel:
find -iname "helloworld.txt") & (sleep 5; echo "Timeout exceeded, killing process"; kill $!)
functionsTo dene a function in bash, use a non-keyword and append opening and closing parentheses. Here a functiongreet is dened and it prints "Hello, world!". Then it is called:
greet()
echo "Hello, world!"
http://www.linuxintro.org/wiki/Backgroundftp://user:password@server/tmp/dblog.log -
7/21/2019 Bash by Examples - LinuxIntro
10/14
4/27/15, 3:10 PaBE - Bash By Examples - LinuxIntro
Page 10 otp://www.linuxintro.org/wiki/BaBE
greet
react on CTRL_CThe command trap allows you to trap CTRL_C keystrokes so your script will not be aborted
#!/bin/bash
rap shelltrap INT
helltrap()
echo "You pressed CTRL_C, but I don't let you escape"
hile true; do read line; done
NoteYou can still pause your script by pressing CTRL_Z, send it to the background and kill it there. To catchCTRL_Z, replace INT by TSTP in the above example. To get an overview of all signals that you might beable to trap, open a console and enter
kill -l
helpful programs
awk: read a specic column
wk is a program that is installed on almost all Linux distributions. It is a good helper for text stream processing.t can extract columns from a text. Let's imagine you want to use the program vmstat to nd out how high the
CPU user load was. Here is the output from vmstat:
rocs -----------memory---------- ---swap-- -----io---- -system-- -----cpu------r b swpd free buff cache si so bi bo in cs us sy id wa st1 0 0 1304736 190232 885840 0 0 20 8 11 17 1 0 99 0 0
We see the user load is in colum 13, and we only want to print this column. We do it with the followingommand:
vmstat 5 | awk '{print $13}'
This will print a line from vmstat all 5 seconds and only write the column 13. It looks like this:
http://www.linuxintro.org/wiki/Vmstathttp://www.linuxintro.org/wiki/Programhttp://www.linuxintro.org/wiki/Awkhttp://www.linuxintro.org/wiki/Open_a_consolehttp://www.linuxintro.org/wiki/Background -
7/21/2019 Bash by Examples - LinuxIntro
11/14
4/27/15, 3:10 PaBE - Bash By Examples - LinuxIntro
Page 11 otp://www.linuxintro.org/wiki/BaBE
# vmstat 5 | awk '{print $13}'
us
To store the CPU user load into a variable we use
oad=$(vmstat 1 2 | tail -n 1 | awk '{print $13}')
What happens here? First vmstat outputs some data in its rst line. The data about CPU load can only be rubbishbecause it did not have any time to measure it. So we let it output 2 lines and wait 1 second between them ( =>vmstat 1 2 ). From this command we only read the last line ( => tail -n 1 ). From this line we only print column3 ( => awk '{print $13}' ). This output is stored into the variable $load ( => load=$(...) ).
grep: search a stringgrep is a program that is installed on almost all Linux distributions. It is a good helper for text stream processing.t can extract lines that contain a string or match a regex pattern. Let's imagine you want all external links from
www.linuxintro.org's main page:
get -O linuxintro.txt http://www.linuxintro.orggrep "http:" linuxintro.txt
sed: replace a stringed is a program that is installed on almost all Linux distributions. It is a good helper for text stream processing.t can replace a string by another one. Let's imagine you want to print your distribution's name, but lsd_release
outputs too much:
# lsb_release -dDescription: openSUSE 12.1 (x86_64)
You want to remove this string "Description" so you replace it by nothing:
sb_release -d | sed "s/Description:\t//"penSUSE 12.1 (x86_64)
Once you understand regular expressions you can use sed with them:
to replace protocol names for a given port (in this case 3200) in /etc/services:
http://www.linuxintro.org/wiki/Regular_expressionshttp://www.linuxintro.org/wiki/Programhttp://www.linuxintro.org/wiki/Sedhttp://www.linuxintro.org/http://www.linuxintro.org/wiki/Regexhttp://www.linuxintro.org/wiki/Programhttp://www.linuxintro.org/wiki/Grep -
7/21/2019 Bash by Examples - LinuxIntro
12/14
4/27/15, 3:10 PaBE - Bash By Examples - LinuxIntro
Page 12 otp://www.linuxintro.org/wiki/BaBE
ed -ri "s/.{16}3200/sapdp00 3200/" /etc/services
if you have an apache web server here's how you get the latest websites that have been requested:
r: replace linebreaks
ed is a program that is installed on almost all Linux distributions. It is a good helper for text stream processing.t can replace a character by another one, even over line breaks. For example here is how you remove all emptyines from your processor information:
wc: countWith the command wc you can count words, characters and lines. wc -l counts lines. For example to nd out howmany semicolons are in a line, use the following statement:
hile read line; do echo "$line" | tr '\n' ' ' | sed "s/;/\n/g" | wc -l; done
t lets you input a line of text, counts the semicolons in it and outputs the number.
How does it do this?
t reads lines from your keyboard (while read line). It outputs the line (echo "$line"), but it does not output it inhe console. The pipe (|) redirects the output to the input stream of the command tr. The command tr replaces the
ENTER ('\ ') by a space (' '). The pipe (|) redirects the output to the input stream of sed. sed substitutes ("s/) theemicolon (;) by (/) a linefeed (\ ), globally (/g"). The pipe redirects the output to the input stream of the wc -lommand that outputs the count of lines.
dialog: create dialogs
Dialog is a command that helps you creating dialogs in the shell. The answers given by the user are send to stderrnd/or inuence the command's return code. For example if you run this script:
#!/bin/bashf (dialog --title "Message" --yesno "Are you having fun?" 6 25)hen echo "glad you have fun"lse echo "sad you don't have fun"i
at /var/log/apache2/access_log | sed "s;.*
-
7/21/2019 Bash by Examples - LinuxIntro
13/14
4/27/15, 3:10 PaBE - Bash By Examples - LinuxIntro
Page 13 otp://www.linuxintro.org/wiki/BaBE
t will display this dialog:
This has been taken from http://www.linuxjournal.com/article/2807. Read there for more info.
See alsobashshellscriptingbash operatorshttp://en.wikibooks.org/wiki/Bash_Shell_Scriptinghttp://ryanstutorials.net/linuxtutorial/scripting.phphttp://wiki.linuxquestions.org/wiki/Bash_tipshttp://wiki.linuxquestions.org/wiki/Bashhttp://linuxcong.org/Bash_scripting_Tutorialhttp://steve-parker.org/sh/intro.shtmlhttp://mywiki.wooledge.org/BashFAQhttp://mywiki.wooledge.org/BashPitfalls
Facebook social plugin
Also post on Facebook
Posting as Laith Al Obaidy ! Comment
Add a comment...
https://www.facebook.com/plugins/comments.php?api_key=203018859828162&channel_url=http%3A%2F%2Fstatic.ak.facebook.com%2Fconnect%2Fxd_arbiter%2FKvoNGODIqPG.js%3Fversion%3D41%23cb%3Df1d600a8d4%26domain%3Dwww.linuxintro.org%26origin%3Dhttp%253A%252F%252Fwww.linuxintro.org%252Ff3d85a49bc%26relation%3Dparent.parent&colorscheme=light&href=http%3A%2F%2Fwww.linuxintro.org%2Fwiki%2FBaBE%20-%20Bash%20By%20Examples&locale=en_US&numposts=5&sdk=joey&skin=light&width=470#https://www.facebook.com/plugins/comments.php?api_key=203018859828162&channel_url=http%3A%2F%2Fstatic.ak.facebook.com%2Fconnect%2Fxd_arbiter%2FKvoNGODIqPG.js%3Fversion%3D41%23cb%3Df1d600a8d4%26domain%3Dwww.linuxintro.org%26origin%3Dhttp%253A%252F%252Fwww.linuxintro.org%252Ff3d85a49bc%26relation%3Dparent.parent&colorscheme=light&href=http%3A%2F%2Fwww.linuxintro.org%2Fwiki%2FBaBE%20-%20Bash%20By%20Examples&locale=en_US&numposts=5&sdk=joey&skin=light&width=470#https://developers.facebook.com/docs/plugins/?footer=1https://developers.facebook.com/docs/plugins/?footer=1http://mywiki.wooledge.org/BashPitfallshttp://mywiki.wooledge.org/BashFAQhttp://steve-parker.org/sh/intro.shtmlhttp://linuxconfig.org/Bash_scripting_Tutorialhttp://wiki.linuxquestions.org/wiki/Bashhttp://wiki.linuxquestions.org/wiki/Bash_tipshttp://ryanstutorials.net/linuxtutorial/scripting.phphttp://en.wikibooks.org/wiki/Bash_Shell_Scriptinghttp://www.linuxintro.org/wiki/Bash_operatorshttp://www.linuxintro.org/wiki/Scriptinghttp://www.linuxintro.org/wiki/Shellhttp://www.linuxintro.org/wiki/Bashhttp://www.linuxjournal.com/article/2807http://www.linuxintro.org/wiki/File:Snapshot-dialog.png -
7/21/2019 Bash by Examples - LinuxIntro
14/14
4/27/15, 3:10 PaBE - Bash By Examples - LinuxIntro
Page 14 otp://www.linuxintro.org/wiki/BaBE
Retrieved from "http://www.linuxintro.org/index.php?title=BaBE_-_Bash_By_Examples&oldid=19055"Category: Learning
This page was last modied on 12 April 2015, at 09:47.This page has been accessed 9,881 times.
http://googleads.g.doubleclick.net/aclk?sa=l&ai=Ct607OpY-VZSMCcyEpgPLl4C4CYiPqvwJyOqMl7ACuLr04OgBEAEgAGDJ1oOI8KPsEoIBF2NhLXB1Yi01OTg2NDM1NTY4NTM2NDkwoAGYmuG-A8gBAqgDAcgDwQSqBI4BT9DnhXaCEgXSNFGvZW305IebgtvTRxBkAqGbeJh5G0tuBL0IF1GPk3qti9s-T42NGYeiEftOY_nTrWhUUBJSApFTkGsOCm1hn_ESABN3WdrprWdBrzkD08UHaiKiNocOiEX4Ne49O73n3hpknsOXHOYWebD8censSm5iv-8l-3p3M7spImZhBoB04giSs6AGAtgHAA&num=1&sig=AOD64_1zi_0eIkY_D6EbhC9jKrVcErUJBQ&client=ca-pub-5986435568536490&adurl=http://catalogicsoftware.com/en/products/trial/http://www.linuxintro.org/wiki/Special:Categorieshttp://www.linuxintro.org/index.php?title=BaBE_-_Bash_By_Examples&oldid=19055http://www.linuxintro.org/index.php?title=Category:Learning&action=edit&redlink=1