Basic Shell (Console) operation for beginners

Booting, installing, newbie
Message
Author
Bruce B

#61 Post by Bruce B »

Shell Expansion

an alias is written like this:

alias myname='echo Bruce'

If I type myname, it will say Bruce on the console.

If I write the alias below I don't need the apostrophe

alias cls=clear

The reason why I don't need an apostrophe is because there are no
spaces in the alias.

Spaces are command delimiters. If we don't tell bash that our
command string with spaces is to be treated as a whole, it will treat
it as individual instructions each time it encounters a space and
bomb out.

I want to demonstrate variable expansion.

1) echo '$PATH'

2) echo "$PATH"

3) echo $PATH

You can select the command, the click you mouse wheel into the
console to save typing.

~

Bruce B

#62 Post by Bruce B »

Keeping File Names Clean

My theory is many FOSS authors actually try and make Linux
friendly to Windows users. Many Linux utilities and programs now
work on 'dirty' Windows file names. Years ago, many Linux apps
would bomb out on bad file names.

Which ones and how many? I don't know. Knowing would be a
discovery process.

What I do is I clean up dirty filenames, so they will work with any
Linux utility or program and make our scripting easier.

Here is what I consider dirty filename for Linux

Elton John - I Don't Wanna Go On With You Like That.mp3

Here is the cleaned filename

Elton_John_-_I_Dont_Wanna_Go_On_With_You_Like_That.mp3

The worst part of the filename was the apostrophe in the word Don't

I think you will find the 'cleaned' file as easy to read as the 'dirty'
one.

If I keep my filenames 'clean'. I don't have to worry about what a
script will do when it processes them.

About six years ago I donated a script, one I didn't write, to Puppy.
It's name is spacereplace. Barry still includes it.
Use it to replace spaces with underscores.

For fine editing, the utility 'ytree' has been the best one I've found,
for ease of use.

Hint: Open it in the directory you want to work in. Hit enter to bring
all the files into a more full window. The rest is intuitive.

Compiling is straight forward

./configure
make install


Don't use the one hosted on Puppy's archive, something is wrong.
Also, it might be an older version.

Get it here

http://www.han.de/~werner/ytree.html


~

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

#63 Post by jpeps »

Bruce B wrote:Using too many commands (words)

Code: Select all

#!/bin/bash

   # get mounted filesystems 
   mntdirs=`cat /proc/mounts | grep /mnt/ \
   | cut -d " " -f 2 | tr "\n" " "`
   echo $mntdirs 
   
   # get mounted filesystems - REFINED FOR SPEED/EFFICIENCY 
   mntdirs=`</proc/mounts grep /mnt/ \
   | cut -d " " -f 2`
   echo $mntdirs 
~
Hi Bruce,

Probably getting beyond a beginners tutorial, but....

Really, you're just substituting one command for another, "cat" for "<" ("<" is just a redirect command). Both do pretty much the same thing.

Regarding the "tr" command, I don't think it's doing anything in the first example anyway, so you could get rid of it. VAR=`cat /file` acts as a redirect with no newlines.

Code: Select all

VAR=`cat /file`
echo $VAR
echo
VAR=`</file`
echo $VAR

Bruce B

#64 Post by Bruce B »

jpeps wrote: Hi Bruce,

Probably getting beyond a beginners tutorial, but....
Hi jpeps,

You are reading and thinking, what more could I want? If everyone did
that, I'd be overjoyed.
jpeps wrote:Really, you're just substituting one command for another,
"cat" for "<" ("<" is just a redirect command). Both do pretty much the
same thing.
What I wrote was:
  • In the refined block we have eliminated two external commands,
    cat and tr.
The emphasis would have been eliminated two external commands.

You're right about the tr being useless, but obviously when I wrote the
script I thought I needed it.

If we have a choice between an internal command and an external
command - everything equal - we want the internal command. The
reason why is - it is already there. An external command has to be
located and copied to memory to be used.

I think redirection and piping may not even be commands in a
conventional sense. Rather an integral part of the kernel's I/O
(input/output) functions. I could be wrong.

I just did a little searching to determine for sure, but didn't come up with
anything conclusive or inconclusive.

I'll leave it as another unanswered ??? among my myriads of unanswered
questions, until and if I learn the answer.

~

Bruce B

#65 Post by Bruce B »

Making Life Easier

Our Linux system may contain 2 or 3 thousand executable files in our
path statement.

I don't remember the names of all the files.

I might be able to remember part of the name. If I remember the first
letters, tab completion can help me.

Otherwise?

Well these files are stored in numerous bin and sbin directories, and it is
a lot of work finding them by reading all the filenames in these directories.

Here is my idea of a helpful script

Code: Select all

#!/bin/bash

# we generally want to initialize our variables at the top of the file

[ ! $1 ] && echo "Argument missing, exiting" && exit

MODPATH=`echo /root/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin:\
/usr/X11R6/bin:/usr/lib/qt/bin:/usr/local/sbin:/usr/sbin:/sbin`

BINDIRS=`echo "$MODPATH" | tr : " "`

# did it work? test

#echo $MODPATH
#echo $BINDIRS

#exit

# it worked, I now have all my bin directories stored in BINDIRS separated
# by spaces, which I will need for the for loop

for i in $BINDIRS
do
	find $i -maxdepth 1 -type f | grep $1
done

# I discovered some directories in the path statement don't exist
# /opt/bin/ /usr/local/games/ /usr/lib/java/jre/bin/
# I could modify the path statement but I'll make the mods in the script
# by removing these directories
# I added MODPATH to accomplish this

Without the comments our simple but useful script looks like this:

Code: Select all

#!/bin/bash
[ ! $1 ] && echo "Argument missing, exiting" && exit

MODPATH=`echo /root/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin:\
/usr/X11R6/bin:/usr/lib/qt/bin:/usr/local/sbin:/usr/sbin:/sbin`

BINDIRS=`echo "$MODPATH" | tr : " "`

for i in $BINDIRS ; do
	find $i -maxdepth 1 -type f | grep $1
done
Remember we want to give our programs meaningful names

Linux comes with a utility called "which", but to use it, we need to know
the filename. And it's for locating the path of a known filename.

I call this script whichx, which means to me - which-extended

If I type in this command

whichx cups it will show me the full path and
name of every file containing the text "cups"

Note the use of the escape character \ at the end of the first line of
MODPATH. Bash uses the end of line to signal end of command. If we
wish to keep long lines short we can use \ to tell bash the command
continues to the next line. You cannot have any spaces after the \.


I've tested whichx and included it as a downloadable script.

You will have to adjust or at least test the variable called MODPATH to
make it right for your system.


~
Attachments
whichx.zip
(350 Bytes) Downloaded 502 times

Bruce B

#66 Post by Bruce B »

Linux is a Unix clone.

The authors working on Linux tended not to make too many utilities not
included in Unix.

ls is the Linux equivalent of the MS dir command.

I liked the dir command. If I wanted to see all the directories and only
directories, I could type 'dir /ad'

With ls or find it is not so easy, yet we can make scripts to add utilities
which don't exist.

I want, for example, to be able to:

* view all non-hidden directories
* nicely formatted
* in dictionary order
* and have an intuitive filename for my script

I can do this, it takes a few minutes to write the script, from then on I
have the script for my Linux systems. This is why I keep my scripts in
their own directories, it is easy for me to retrieve my scripts to new Linux
installs.

My intuitive filename is: ad (that was the switch used in the dir
command and it means to me 'all directories', (only my script doesn't
show the hidden ones, on purpose)

Next I'll explain the commands

find . -type d -maxdepth 1

. is our current directory
-type d means display the type directory - not files
-maxdepth 1 means I don't want to see any subdirectories

grep -v '^\./\.'

grep -v , the -v switch means display everything that does not match my
criteria

'\./\.' is my criteria, using the find command the beginning of hidden
directories, looks like this ./. , if I want grep to look for literal periods, I
have to escape them. Remember our common escape character is the \ ,
the ' ' are used to tell grep the beginning and end of our criteria and don't
allow for any shell expansion

cut -d "/" -f 2

The cut command can be used to remove output, the find command will
output a directory like this; ./foobar , we want it to display only foobar,
the cut command uses / as the delimiter,
like this -d "/" and the -f switch says print only text after field 1

sort -d will sort our text, the -d switch says to do it in dictionary order.
Linux is case sensitive and we want to display like this:

mydocuments
MyFiles

Which would be a non case sensitive sort

grep -v '^\.$' will eliminate a line which only has a period

^ means start of line
$ means end of line
\ escapes the period

We pipe to filter output, the pipe symbol is | , the output from the
command on the left, becomes the input for the command on the right.
When done, the filtered output is displayed on screen.

Now, the parts of the script have been explained, we can put them
together.

Code: Select all

#!/bin/bash
find . -type d -maxdepth 1 | grep -v '^\./\.' | cut -d "/" -f 2 | sort -d | grep -v '^\.$'
When you run ad on the command line, it will display nicely formatted
sub-directories in your current directory.

~

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

#67 Post by jpeps »

Bruce B wrote:

Code: Select all

#!/bin/bash
find . -type d -maxdepth 1 | grep -v '^\./\.' | cut -d "/" -f 2 | sort -d | grep -v '^\.$'
When you run ad on the command line, it will display nicely formatted
sub-directories in your current directory.

~
You'll probably get an error, since (normal) options have to come before args, and -type is an arg (or "positional" option)

Bruce B

#68 Post by Bruce B »

jpeps wrote: You'll probably get an error, since (normal) options have to come before args, and -type is an arg (or "positional" option)
Try it, if there is a problem, we can debug it.

File attached.
Attachments
ad.zip
(222 Bytes) Downloaded 494 times
Last edited by Bruce B on Fri 11 Mar 2011, 08:31, edited 1 time in total.

Bruce B

#69 Post by Bruce B »

jpreps,

I don't see a problem with your logic, so I modified it and attached a modified file.

admodified

Bruce

Note: I found one switch improvement, changed sort -d option to sort -f
Attachments
admodified.zip
(238 Bytes) Downloaded 515 times

Bruce B

#70 Post by Bruce B »

CLI variables AKA arguments AKA parameters AKA ???

We've seen plenty of examples of variables in our scripts.

This brief post will serve as a primer to introduce you to the command
line variables.

I use the for loop. The for loop has not been explained YET. But I will.

Life is easier because I now have an official editor - jpreps

If I goof, or boo-boo, I get free help. This is one of the advantages on
FOSS development - peer review.

Code: Select all

#!/bin/bash

c=0

for i in $0 "$@" ; do
	echo \$$c is $i
	c=`expr $c + 1`
done
The program name is cliargs.

Here are some usage examples:

cliargs
cliargs your name
cliargs your\ name
cliargs "your name"
cliargs 1234 Main Street
cliargs "1234 Main Street"


cliargs will enable you to visualize how your
script interprets your command line arguments

zip file attached
Attachments
cliargs.zip
(224 Bytes) Downloaded 514 times

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

#71 Post by PupGeek »

Bruce, I am not too clear on why you placed the three echo statements a few posts back. I tried them each and noticed that while the $PATH and "$PATH" were treated as variables, the '$PATH' was treated as a literal. Are what's contained in single quotes always treated as a literal in echo statements?

Oh, and would you be able to make a thread all about regular expressions? That stuff just throws me way off, and I haven't seen too much in the docs about it, but it can probably be very useful to me if I knew better how to use it.

Bruce B

#72 Post by Bruce B »

PupGeek wrote:Bruce, I am not too clear on why you placed the
three echo statements a few posts back. I tried them each and
noticed that while the $PATH and "$PATH" were treated as variables,
To show that two would behave the same
One wouldn't
PupGeek wrote:. . . the '$PATH' was treated as a literal. Are
what's contained in single quotes always treated as a literal in echo
statements?
Maybe always. Maybe sometimes they drive you crazy.

The general rule is single quotes when used in variables inhibit
expansion.
PupGeek wrote:Oh, and would you be able to make a thread all
about regular expressions? That stuff just throws me way off, and I
haven't seen too much in the docs about it, but it can probably be
very useful to me if I knew better how to use it.
It could throw anyone way off, if not presented on a very easy
gradient from start to finish.

Puppy's help system contains a page on regular expressions.

I think a page could be started in the programming section of the
forum for people wishing to learn and ask questions.

What do you think about that?

~

I've been using some regular exr

User avatar
puppyluvr
Posts: 3470
Joined: Sun 06 Jan 2008, 23:14
Location: Chickasha Oklahoma
Contact:

#73 Post by puppyluvr »

:D Hello,
OK, so how do I get this whole thread as a text file... 8)

OK, really, probably a noob question, but if I write scripts using alias`s on my system, they will not run on other systems???
Close the Windows, and open your eyes, to a whole new world
I am Lead Dog of the
Puppy Linux Users Group on Facebook
Join us!

Puppy since 2.15CE...

Bruce B

#74 Post by Bruce B »

puppyluvr wrote: OK, really, probably a noob question, but if I write scripts using
alias`s on my system, they will not run on other systems???
Since the days of Moses, Puppy started using BusyBox extensions for
its common command utilities.

I like using genuine utilities.

This can cause some differences which need adjusting when porting.

I recently setup 5.20 and ported my mountcontrol script to Puppy. It
wouldn't mount an NTFS partition. An on screen failure about not
understanding a -f or something.

My script was written for the true mount command. Puppy's mount
command is a script written by Barry.

The real mount command in Puppy is called mount-FULL

I did a search and replace. Replaced all instances of mount with
mount-FULL

~~~~~~~~~~~~~~

When we make our scripts, we want them portable. I already knew
about Puppy's mount-FULL, because of this I could have made the
'control center' automatically portable with a couple simple
commands at the top of the script by using a variable for the
command 'mount'. Very simple, as shown below.

Code: Select all

mntcmd=mount
[ -f /bin/mount-FULL ] && mntcmd=mount-FULL
The 'control center' would have adjusted itself with no user
intervention.

Where I often have problems when porting scripts is directories
don't exist on the new setup which existed on the old one.

This is why we want to keep in mind conditional checks and
branches when writing scripts.

Here is an example:

Code: Select all

[ ! -d $destdir ] && echo "$destdir doesn't exist, exiting" && exit
Note here how a potentially damaging script becomes safe.
I check the condition, branch to a message, branch to quit.

Ideally you would use so much care, you could hand your script to
another Puppy user and have it work.

If you wish to share scripts, you must think of a lot of things, far
beyond your individual setup. Also, that a script might be floating
around for years.

Here is an example of conditional checks and branching. We want to
make sure the user is advised, if he is not using 5.20

Code: Select all

grep DISTRO_VERSION=520 /etc/DISTRO_SPECS>/dev/null
if [ "$?" -ne "0" ] ; then
	echo " This script was written and tested for Puppy version 5.20"
	echo " You are "not" using this version, there may be unexpected"
	echo -n " problems, do you wish to continue (y,n)? "
	read a
	if [ "$a" != "y" ] ; then
		echo;echo " You choose not to continue, no changes made"
		exit
	fi
fi
Please note how we indent and nest our statements and commands.
It makes reading much easier.

On second thought, I'll explain. If you are working in a group, your
friends won't like it if you don't indent. And in a group do things by
convention, such as variables in UPPERCASE.

if begins our if statement, fi ends it.

By indenting everything inside it, we can easily see where the if
statement begins and ends. Simply look straight down the column
for the end of the statement.

I put an if statement inside an if statement and indented again.

Look at the difference in readability with and without indenting.

Code: Select all

grep DISTRO_VERSION=520 /etc/DISTRO_SPECS>/dev/null
if [ "$?" -ne "0" ] ; then
echo " This script was written and tested for Puppy version 5.20"
echo " You are "not" using this version, there may be unexpected"
echo -n " problems, do you wish to continue (y,n)? "
read a
if [ "$a" != "y" ] ; then
echo;echo " You choose not to continue, no changes made"
exit
fi
fi

Code: Select all

grep DISTRO_VERSION=520 /etc/DISTRO_SPECS>/dev/null
if [ "$?" -ne "0" ] ; then
	echo " This script was written and tested for Puppy version 5.20"
	echo " You are "not" using this version, there may be unexpected"
	echo -n " problems, do you wish to continue (y,n)? "
	read a
	if [ "$a" != "y" ] ; then
		echo;echo " You choose not to continue, no changes made"
		exit
	fi
fi
This example is a very small snippet. You can run into statements
that begin and end a hundred lines later. More lines than can be
viewed in the editor at one time.

~

Bruce B

#75 Post by Bruce B »

puppyluvr wrote: [but if I write scripts using alias`s on my system, they will not run on other systems???
Second answer.

When run a script, it runs in a child shell. The aliases don't get
carried over. Simply stated; they are not available to the script.

When you port your ~/.bashrc file, it is a good idea to open it and
read the lines.

Maybe there are change directory aliases, but on your new setup
the directories don't exist.

Maybe you were using an editor that doesn't exist.

Probably, when you review the file, you will think of better
ways to do things and improve the file.

~

Bruce B

#76 Post by Bruce B »

Just for fun, how fast can your computer execute 1,000,000 commands?

The script will execute
date 2x
: 999,998x

: is a command which says do nothing and give an successful error
code which would be 0

Code: Select all

#!/bin/bash

date
for ((i=1;i<999999;i++));do
:
done
date
It takes my midrange machine about 17 seconds

Script name: millionx (attached)

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

~

EDIT - an improved millionx file is available down a few posts, better to
use it.
Attachments
millionx.zip
(219 Bytes) Downloaded 322 times
Last edited by Bruce B on Sun 13 Mar 2011, 01:00, edited 1 time in total.

Bruce B

#77 Post by Bruce B »

The if statement

This script gives examples of
  • the if statement
    conditional checks and branching according to the condition
    using echo -n for echoing output without a linefeed
    how to get user input from within the program
    how to quote variables in on screen output
    using echo to print and format the output
    the 'exec' command to start a new script and terminate the existing script
I recommend downloading, reading, studying and running this script
You will be using the if statement and other commands in the script
over and over again when writing your scripts.

The 'for loop' is another which need be committed to memory.

Code: Select all

#!/bin/bash

echo -n "Please enter a primary color: "
read clr
echo

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	

echo
echo -n "Again (y,n)? "
read -n 1 a
echo

if [ "$a" = "y" ] ; then 
	echo 
	exec $0

fi

echo
script name: colors, file attached

~
Attachments
colors.zip
(412 Bytes) Downloaded 349 times

Bruce B

#78 Post by Bruce B »

In a recent post I presented an idea of 'something in - something out'

We all know the concept unconsciously. We press the 'm' key, this is input.
We expect to see 'm' echoed as output on the screen. When it doesn't happen,
we think something is wrong. What is wrong can be conceptualized
as an input/output problem.

In this post I want to talk about thinking in terms of true and false.
If we are sane, we don't think in absolutes. In programming, true
and false is often all we are making our decisions on. If you program
for several years, you will probably lose sanity.

My advice is, after the sanity is lost, be calm, quite, soft spoken,
articulate and whatever you do, don't appear to be a danger to
others. Chances are they won't lock you up, if you take my advice.

Let's look at our if statement from a true / false perspective.

Code: Select all

if [ "$clr" = "red" ] ; then
	if false no commands execute
	if true the commands execute
elif [ "$clr" = "green" ] ; then
	the elif is shorthand for 'else if'
	the only chance of the elif running commands is if the 'if' was not true
	the elif can only execute if it is true
	if false nothing happens
elif [ "$clr" = "blue" ] ; then
	same as above
elif [ "$clr" = "yellow" ] ; then
	same as above above
else
	if none of our if or elif statements were true
	the else commands will execute
	they will only execute under these circumstances
fi	
We have five possible conditions, but only one will execute commands

We only need the 'elif' and 'else' - if we need them.

The basic if statement is like this

Code: Select all

if [ "3" = "4" ] ; then
	echo 3 equals 4
fi
3 doesn't equal 4 so nothing happens, because it is a false condition

Code: Select all

if [ "4" = "4" ] ; then
	echo 4 equals 4
fi
Above we have a true condition, so the command runs.

Code: Select all

if [ "3" = "4" ] ; then
	echo 3 equals 4
else
	echo 3 does not equal 4
fi
See how it works, the first test is false, we programmed in the else.
The else executes because the first 'if test' was false. If it were true
the else would not execute commands.

~

Bruce B

#79 Post by Bruce B »

Piping commands through scripts - introduction

We can make some very useful scripts (and C programs) for use as
pipes.

I'll give a couple bare bones examples

Filename: upperc
contents:
tr "a-z" "A-Z"

Filename lowerc
contents:
tr "A-Z" "a-z"

To make the pipes, put the corresponding line at the top of the file,
name the file and make it executable.

Then if you want to change case of a string of text or even a file, you
can pipe the text through the executable text file.

You can actually pipe through some complex scripts, but this is just
an introductory to the concept.

~

Bruce B

#80 Post by Bruce B »

About Characters

Our characters are not really characters from the computer's perspective.
They are binary values.

There are currently eight people in the whole world, aliens maybe, who
can read binary strings.

Thousands of propeller heads can read octal and hex.

Normal people read decimal math. Although hex is very useful in
programming.

Each character we see doesn't exist except by translation from binary to
character.

Sometimes we want to know the value of our characters, especially in C
and probably other programs.

The following program will display characters and their decimal
equivalents in your bash shell.

You might want to keep the program for future reference.

After the program runs, you can scroll up to see what scrolled off screen.

Code: Select all

#!/bin/bash

for ((i=33;i<127;i++)) ; do
	printf "\x$(printf %x $i )"
	echo "  has decimal value of $i"
done
Script file attached

~
Attachments
charvalues.zip
(255 Bytes) Downloaded 336 times
Last edited by Bruce B on Sat 12 Mar 2011, 15:57, edited 1 time in total.

Post Reply