Basic Shell (Console) operation for beginners

Booting, installing, newbie
Post Reply
Message
Author
Bruce B

#81 Post by Bruce B »

A C type 'for loop' construct

I've used this construct twice so far, without explanation.

for ((i=33;i<127;i++))

i=33 initializes the variable i with the value of 33
i<127 terminates the loop after count reaches 126
i++ increments the value by one on each iteration

You can use this construct when you need a loop that counts. It is not
used much in bash, but used extensively in C

Another way is use the normal for loop like this

for i in 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 and etc.

But that is work, we want better ways to improve our laziness.

Try this on the command line

# myvar=`echo {33..126}` (those are braces and backticks)

then

# echo $myvar

After setting the variable, you could then use the conventional
for construct

for i in $myvar

~
Last edited by Bruce B on Sat 12 Mar 2011, 17:13, edited 2 times in total.

jpeps
Posts: 3179
Joined: Sat 31 May 2008, 19:00

#82 Post by jpeps »

Bruce B wrote:
Isn't there a command for timing execution? If so, what's its name?

~
"timer" script; put in $PATH

Code: Select all

#!/bin/sh

#### begin with:  "timer & " 
###  end with:    "kill `pidof timer` " 

SEC="0"

echo -en "\nWorking..............."
while [ "$0" ]; do
  for ((i=0;i<1000001;i++)); do 
  
    SEC="$(( $SEC+1 ))"
 [ ${SEC} -gt 0 -a ${SEC} -lt 11 ] &&  echo -en "$SEC"   
 [ ${SEC} -gt 10 -a ${SEC} -lt 101 ] &&  echo -en "\b$SEC"   
 [ ${SEC} -gt 100 -a ${SEC} -lt 1001 ] &&  echo -en "\b\b$SEC"   
 [ ${SEC} -gt 1000 -a ${SEC} -lt 10001 ] &&  echo -en "\b\b\b$SEC"   
 [ ${SEC} -gt 10000 -a ${SEC} -lt 100001 ]  &&  echo -en "\b\b\b\b$SEC"   
 [ ${SEC} -gt 100000 -a ${SEC} -lt 1000001 ] &&  echo -en "\b\b\b\b\b$SEC"   
    echo -en "\b"
    sleep 1
   done
done
Then:

Code: Select all

#!/bin/bash 

date
exec timer &
for ((i=1;i<99999;i++));do
:
done
date
kill `pidof timer`

User avatar
Moose On The Loose
Posts: 965
Joined: Thu 24 Feb 2011, 14:54

#83 Post by Moose On The Loose »

Bruce B wrote:A C type 'for loop' construct

# myvar=`{33..126}` (those are braces and backticks)

Code: Select all

# myvar=`{1..10}`
bash: 1: command not found


# myvar=`echo {33..126}`
# echo $myvar
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
#

Bruce B

#84 Post by Bruce B »

Moose On The Loose,

Thanks, I fixed the original post.

Bruce

I could say, I'm doing this to demonstrate that FOSS is a better way of
development because of peer review. But probably, I had insomnia. Also
known as sleeping at the keyboard.

Bruce B

#85 Post by Bruce B »

jpeps,

The timer script is a keeper. Thanks.

I found a perfect second timer for us. I'll post and explain it later.

As mentioned, I taught myself, mostly through books. My dad was/is a
computer scientist, which I found helpful. Still, most of what I learned is
self taught.

What I found over and over is the authors would do OK for a few chapters,
then get over my head. I call it an easy gradient followed by too steep a
gradient.

I would like to teach a lot of basics, both concepts and language.

I really don't want to do what others did to me, which is hit me with a
steep gradient.

You know enough, you may not catch it if the gradient was too steep.

I would like however some PMs advising me about the gradient and if the
teaching is happening without too much brain strain.

Bruce

I also wonder if it is a good thing to listen to Pink Floyd at 77% volume
while doing this.

~

amigo
Posts: 2629
Joined: Mon 02 Apr 2007, 06:52

#86 Post by amigo »

'time' is the command for timing operations. If you need to time the toal of a bunch of repitions, then put the repeating vommands in a function and then: 'time func_name' should give the total of all the loops.

jpeps
Posts: 3179
Joined: Sat 31 May 2008, 19:00

#87 Post by jpeps »

amigo wrote:'time' is the command for timing operations. If you need to time the toal of a bunch of repitions, then put the repeating vommands in a function and then: 'time func_name' should give the total of all the loops.
also can run "time myscript"

PupGeek
Posts: 353
Joined: Sun 06 Sep 2009, 11:30

#88 Post by PupGeek »

Bruce B wrote: What I found over and over is the authors would do OK for a few chapters, then get over my head.
Same here.... every time..... and it always gets crazy right around variables and expressions. And arrays? forget it.

I think there are not enough examples to cover every scenario and that some of the examples are not very interesting as well. When I was in college for electronics, we (meaning the professor and the students) engineered and built a laboratory power supply right from the ground up. We all had a voice and applied our theoretical knowledge and lab experiences for this project. I think this would be a good approach to learning programming too. Kinda what I tried to do when starting this thread.

oh, and as for aliases being portable, could you not define them in the script you want to share? I know this would only be advantageous in long scripts that use the alias(es) numerous times.

Bruce B

#89 Post by Bruce B »

I tried the time command and couldn't figure out how to apply to the
script. Some examples please?

Fortunately, I found Lupu 5.20 replaced the BusyBox date extension with
the 'real' date command, which has a second timer.

This makes the math super easy, just subtract the start time from the
finish time. No hour or minute roll overs to complicate things.

Code: Select all

#!/bin/bash

echo Executing one million commands
start=`date +%s`
for ((i=1;i<999999;i++));do
:
done
stop=`date +%s`
total=`expr $stop - $start`
echo "Total time: $total seconds"
If script doesn't right work on your Puppy, I can upload the real date
command.

~
Attachments
millionx.zip
(289 Bytes) Downloaded 345 times

Bruce B

#90 Post by Bruce B »

PupGeek,

After reading your post, I played some with using aliases for adding color
to text output. I wasn't pleased.

I then made functions and the results looked great.

Adding colored output gives a more professional look to the script. But
colors are a hassle, unless made easy, which I think I did.

You can give the functions the names you want, in this script, I used this pattern:

whi = normal white
bwhi = bright white
and so on
std = return to normal

Script usage examples

cya
echo Puppy Linux
std

# or use ;
gre;echo Lupu 5.20;std

#or

bmag;echo -n "Puppy Linux ";bwhi;echo version 5.20;std
red;echo "-- Read Warning --"
bred;echo "-- Read Warning --";std


The functions

Code: Select all

function bla() {
    echo -en "\033[30m"
}
function red() {
    echo -en "\033[31m"
}
function gre() {
    echo -en "\033[32m"
}
function yel() {
    echo -en "\033[33m"
}
function blu() {
    echo -en "\033[34m"
}
function mag() {
    echo -en "\033[35m"
}
function cya() {
    echo -en "\033[36m"
}
function whi() {
    echo -en "\033[37m"
}
function std() {
    echo -en "\033[0m"
}

function bred() {
    echo -en "\033[31;1m"
}
function bgre() {
    echo -en "\033[32;1m"
}
function byel() {
    echo -en "\033[33;1m"
}
function bblu() {
    echo -en "\033[34;1m"
}
function bmag() {
    echo -en "\033[35;1m"
}
function bcya() {
    echo -en "\033[36;1m"
}
function bwhi() {
    echo -en "\033[37;1m"
}
You can copy and paste the text to the top of your file OR you can import
the functions.

Import Example: . /root/bin/clrs

File attached: clrs
Attachments
clrs.zip
(285 Bytes) Downloaded 333 times
Last edited by Bruce B on Sun 13 Mar 2011, 04:43, edited 1 time in total.

Bruce B

#91 Post by Bruce B »

Our character sets have more characters than our keyboards. Some of
these characters are very useful in presenting our posts and documents
more correctly or better formatted.

echo "¢ £ ¤ ¥ § © « ® ² ³ ¶ · ¹ º » ¼ ½ ¾ ÷ ø"


I called the script xtrachars

We can run the script, it will output to the screen, then select the
characters and click middle mouse button to paste them into our
document. To use for later copying and pasting.

I'm interested in finding some ambitious person to modify the script so
that it pipes the output to the clipboard. This way all we have to do is run
it and click middle mouse button, thus saving some extra work.

~

Bruce B

#92 Post by Bruce B »

Introducing more fun stuff

» while loop
» integer math using the echo command
» x instead of quotes, explained

Code: Select all

#!/bin/bash

# Count by two until we reach 20, then quit
# A trivial program

while [ x$cnt != x20 ] ; do
	cnt=`echo $((cnt + 2))`
	echo $cnt
done
The variable cnt has not been initialized prior to the
start of the loop. This means the loop will run at least one time.

It also means the variable cnt doesn't exist at all
when the loop starts.

In previous examples I used quotes

[ "$cnt" != "20" ]

The reason for the quotes was to have something there which is equal on
both sides of our comparison. We are comparing the value in $cnt with
the value 20

In this example I used x in place of quotes for exactly the same reason, I
used quotes. Note: it is easier to type one lowercase x than two " "

[ x$cnt != x20 ]

What if I didn't use "" or x or something?

Considering that $cnt doesn't exist at the beginning of the loop our test
would look like this:

[ != 20 ]

!= is a comparison operator and there is nothing to compare to. Bash will
see the error, complain and quit.

[ x$cnt != x20 ] is actually [ x != x20 ] , we have something for Bash to
compare and that's all it wants.

This is why we use x's , quotes or something of your choice in these test
statements.

Now you know the echo command can also perform integer math. And the
example shows how it can be done. There are a variety of ways to do
math in our scripts. All in due time.

~

Bruce B

#93 Post by Bruce B »

Introducing the time saving 'printf' statement

For this post, I took a very small snippet of xine -help output.

It has indents to maintain and characters which would throw echo off, if echo were not properly quoted.

Typically bash programmers use the echo command for on screen display.
But when you have a lot of text to display there is a much easier way.

First example: echo command on each line with quotes on non empty
lines. The echo and its quotes do not display on the output.

Code: Select all

echo "Usage: xine [OPTIONS]... [MRL]"
echo
echo "OPTIONS are:"
echo "  -v, --version                Display version."
echo "      --verbose [=level]       Set verbosity level. Default is 1."
echo "  -c, --config <file>          Use config file instead of default one."
echo "  -V, --video-driver <drv>     Select video driver by id. Available drivers:"
echo "                               dxr3 aadxr3 xv SyncFB opengl raw xshm aa caca"
echo "  -A, --audio-driver <drv>     Select audio driver by id. Available drivers:"
echo "                               null alsa oss esd file none"
echo "  -u, --spu-channel <#>        Select SPU (subtitle) channel '#'."
echo "  -a, --audio-channel <#>      Select audio channel '#'."
echo "  -p, --auto-play [opt]        Play on start. Can be followed by:"
echo "                    'f': in fullscreen mode."
echo "                    'h': hide GUI (panel, etc.)."
echo "                    'w': hide video window."
echo "                    'q': quit when play is done."
echo "                    'd': retrieve playlist from DVD. (deprecated. use -s DVD)"
echo "                    'v': retrieve playlist from VCD. (deprecated. use -s VCD)"
echo "                    'F': in xinerama fullscreen mode."
Second example using the bash printf statement. It requires one quote
at the beginning and one quote at the end. The formatting is maintained.
The printf and the two quotes do not display on the output.

Code: Select all

printf "
Usage: xine [OPTIONS]... [MRL]

OPTIONS are:
  -v, --version                Display version.
      --verbose [=level]       Set verbosity level. Default is 1.
  -c, --config <file>          Use config file instead of default one.
  -V, --video-driver <drv>     Select video driver by id. Available drivers:
                               dxr3 aadxr3 xv SyncFB opengl raw xshm aa caca
  -A, --audio-driver <drv>     Select audio driver by id. Available drivers:
                               null alsa oss esd file none
  -u, --spu-channel <#>        Select SPU (subtitle) channel '#'.
  -a, --audio-channel <#>      Select audio channel '#'.
  -p, --auto-play [opt]        Play on start. Can be followed by:
                    'f': in fullscreen mode.
                    'h': hide GUI (panel, etc.).
                    'w': hide video window.
                    'q': quit when play is done.
                    'd': retrieve playlist from DVD. (deprecated. use -s DVD)
                    'v': retrieve playlist from VCD. (deprecated. use -s VCD)
                    'F': in xinerama fullscreen mode.
  -s, --auto-scan <plugin>     auto-scan play list from <plugin>
  -f, --fullscreen             start in fullscreen mode,
  -F, --xineramafull           start in xinerama fullscreen (display on several screens),
"
~

jpeps
Posts: 3179
Joined: Sat 31 May 2008, 19:00

#94 Post by jpeps »

Bruce B wrote:I tried the time command and couldn't figure out how to apply to the
script. Some examples please?

Code: Select all

#!/bin/bash 

date
function million {
for ((i=1;i<999999;i++));do
:
done
}
time million
echo
date

Bruce B

#95 Post by Bruce B »

Jpeps,

Thanks for coming to the rescue. I'll call suicide prevention and tell them
it was just a false alarm.

Have you ever worked with other programmers in a community?

I haven't.

Would you like to do a fairly small group project, here online?

If so, would you be willing to be the benevolent dictator?

Let me know, if you are interested. If so I'll define the project I have in
mind, if you don't like the project, you can change your mind.

Bruce

~

Bruce B

#96 Post by Bruce B »

Introducing the 'case' statement

Earlier, I introduced the if statement with the elif and else

In order to avoid too many elif's, programmers often choose the case
statement when it will work by using words. It is clean and easy to work
with.

I'll show you an example of our earlier if,elif,else structure compared with
the case structure. You will be able to see the difference. Both structures
do the same thing.

Code: Select all

if [ "$clr" = "red" ] ; then
   echo " You entered a valid primary color \"$clr\""
elif [ "$clr" = "green" ] ; then
   echo " You entered a valid primary color \"$clr\""
elif [ "$clr" = "blue" ] ; then
   echo " You entered a valid primary color \"$clr\""
elif [ "$clr" = "yellow" ] ; then
   echo " You entered a primary color used in painting \"$clr\""
else
   echo " \"$clr\" is not known to the program as a primary color"
   echo " We use red, green, and blue as primary colors"   
fi   

Code: Select all

case $clr in

    red)     echo " You entered a valid primary color \"$clr\"" ;;
    green)   echo " You entered a valid primary color \"$clr\"" ;;
    blue)    echo " You entered a valid primary color \"$clr\"" ;;
    yellow)  echo " You entered a primary color used in painting \"$clr\"" ;;
    *)       echo " \"$clr\" is not known to the program as a primary color"
             echo " We use red, green, and blue as primary colors" ;;

esac
In some instances, the case statement would be the better choice.

Until you memorize things it is often wise to copy and paste an example
to a file in your scripts directory.

Suppose we name this file case-example. You can name it how you
want. You could have a file with examples and named such. In a way the
naming doesn't matter because you can grep all your scripts by keyword.
Remember case terminates with case spelled backward, esac.

# grep esac * will find the file with the case example.

~

Bruce B

#97 Post by Bruce B »

An Intrusion Prevention Script

Notes:
  • » logs date and time of each attempt
    » would take a good Linux user to work around
    » shuts machine down on first bad access attempt
    » then all subsequent attempts to enter system
    » traps Ctrl+C and other methods to defeat
    » put script in /etc/profile.local
    » script is partially tested and looks good
    » user can refine
    » ask if you have questions about it
    » displays message -- Unauthorized Access Attempt --
    » subsequent messages -- System has been compromised, shutting down now --

Code: Select all

#!/bin/bash

KEYWORD=foobar
SAFEFILE=/var/log/safe~
trap caught 1 2 3 4 5 6

function std() {
    echo -en "\033[0m"
}

function bred() {
    echo -en "\033[31;1m"
}


function caught() {
	echo date >>$SAFEFILE # remove this echo
	bred
	echo "-- System has been compromised, shutting down now --"
	std
	echo poweroff # remove this echo

}

if [ -f $SAFEFILE ] ; then
	echo date >>$SAFEFILE # remove this echo
	bred
	echo "-- System has been compromised, shutting down now --"
	std
	echo poweroff # remove this echo
fi

echo -n "Login: "
read a
if [ x$a != x$KEYWORD ] ; then
	echo date >>$SAFEFILE # remove this echo
	bred 
	echo -- Unauthorized Access Attempt --
	std
	echo poweroff # remove this echo
fi	

~

amigo
Posts: 2629
Joined: Mon 02 Apr 2007, 06:52

#98 Post by amigo »

Example of using time to time a funtion:

Code: Select all

#!/bin/bash 

function million { 
for ((i=1;i<999999;i++));do 
: 
done 
} 
time million 
On my ancient machine I get this output:
real 1m1.969s
user 0m54.140s
sys 0m1.010s


Another example:
time ls -lR /

User avatar
Moose On The Loose
Posts: 965
Joined: Thu 24 Feb 2011, 14:54

#99 Post by Moose On The Loose »

Bruce B wrote:Introducing more fun stuff

In this example I used x in place of quotes for exactly the same reason, I
used quotes. Note: it is easier to type one lowercase x than two " "

[ x$cnt != x20 ]

What if I didn't use "" or x or something?
~
Another point is that the "$A" construct keeps any spaces that may happen to be in A

Code: Select all

# A="Hi         "
# echo $A c
Hi c
# echo "$A" c
Hi          c
# 
This fact can be useful because you can use spaces in the variables to make columns line up when displayed in one case and leave out the spaces in another.

amigo
Posts: 2629
Joined: Mon 02 Apr 2007, 06:52

#100 Post by amigo »

[ "x$cnt" != x20 ] works just as well. the thing is that with 'sh' (only single-brackets supported), the first value cannot be null. the other way to avoid that is to reverse the values -but it reads really weird:
[ 20 != "$cnt" ]

If you are writing for bash, use double brackets and then the first value can be null and no errors result:
[[ "$cnt" != 20 ]]

Post Reply