Basic Shell (Console) operation for beginners

Booting, installing, newbie
Message
Author
User avatar
Karl Godt
Posts: 4199
Joined: Sun 20 Jun 2010, 13:52
Location: Kiel,Germany

#21 Post by Karl Godt »

For files it is important to use double quotes

but try this
while true; do ps | grep X | grep -v 'grep'; S="/bin/sleep 0.2"; "$S" ;done
and this

Code: Select all

 while true; do ps | grep X | grep -v 'grep'; S="/bin/sleep 0.2"; $S ;done
Things might work differently on "ash and bash" and "rxvt and urxvt" .

Bruce B

#22 Post by Bruce B »

Why use the command line.

In the beginning was the command line. I couldn't build or setup a
computer without using the command line. Today, maybe I could, but
I've not tried it.

The primary reason I use it so extensively today is because it is so much
faster and easier than the GUI in many cases.

In and of itself, I don't think the command line would be faster,
except for the aliases and scripts we make.

Additionally, when the computer doesn't work right, there often isn't a
GUI application to do the troubleshooting and repair. The power user
knows what command line tools are available and how to use them.

Presently, as I write this text, I'm converting .wav files to .mp3 files in
large batch. There is probably a GUI tool to do this. Even if there is, it
won't provide me with the level of control I can get with my own script.

I might have almost one terabyte of data on my computer. Because of
scripts I've written, I can find files much faster than the computer can
search itself with any GUI tool I know of.

~~

Bruce B

#23 Post by Bruce B »

When you start writing your own scripts, you are literally programming.

There are some things you need to know about, things which may seem
odd.

I wish to introduce you to one.

A Shell is an interface to the operating system. We call Bash a shell. But
the GUI is also a shell.

When X is running we run Bash in an emulator. Rxvt, Urxvt, or others.

When we run a script it does NOT run in the same shell we started it in.
It runs in a child or secondary shell and when done with the commands,
returns us to the first shell.

Here is a very simple script that won't seem to work. Please try it.

Scriptname r

Code: Select all

#!/bin/bash
cd /
After you've made it executable, run it. When finished you will still be in
the same directory you ran it in, even though the command is to cd to /

What happened is it actually did cd to / in the child shell, then when
done, left us where we started.

Next take the same script and use this command:

. r

Notice that it changed to the root directory like it was supposed to.

. causes the command to run in the current shell, that's why it works.

.
is a shortcut of sorts for source

source r should achieve the same results

When done, delete the file r, it's purpose is served
and I will show you a much better way.

~

Bruce B

Re: Part 1: Getting started

#24 Post by Bruce B »

Code: Select all

for i in *.deb
do
undeb "$i" #It is a good habit to quote variables.
shift
done
# It is a good habit to quote filenames. $i would have a filename. It is
especially a good habit if one distributes the script.

# The shift in a for loop either shouldn't be there or I don't
understand something.

A filename might contain a space. Without the quotes, it would throw the
script off, because the first space it encounters would be interpreted as a
command delimiter.

Unix people never put spaces in directory or filenames. To do so is stupid.

Windows came up with a hacked LFN and I noticed Gates was so proud
he overcome his 8.3 limits he started putting spaces in directory names.

Windows users started using spaces in directory and filenames to make
them more readable.

Then when they moved to Linux, they brought their fears and computing
habits with them.

Yet, if we look at real programmers, programmers I respect anyway, they
don't use spaces. Check out the system32 directory in Windows for
examples of how people who know what they do name files.

I don't use spaces in file names, so for my own scripts, I wouldn't quote
because I want to see the error message and fix the file.

There are certain characters I don't want in my filenames or at a
minimum I want to know if they exist. For this reason I wrote a script to
check files for characters I don't want.

Code: Select all

#/bin/bash
for i in *
do 

	echo $i | grep " "
	echo $i | grep __
	echo $i | grep \'
	echo $i | grep "?"
	echo $i | grep "("
	echo $i | grep ")"
	echo $i | grep "&"
	echo $i | grep ","
	echo $i | grep "!"

done
The script could be written for much better speed.

Some of these characters are for appearance. But some of these
characters can wreak havoc with our scripts.

Frankly, I think the programmer, especially the beginning programmer,
will discover she's spending most of her time debugging her scripts.

Some of these hard ones to figure is because Windows users make
filenames using characters bash stumbles on if not properly escaped.

~

Bruce B

#25 Post by Bruce B »

Below is a basic order of precedence in which bash finds commands

1st = alias
2nd = function
3rd = internal command
4th = external command


To see the aliases

# alias

To see the functions

# set (then look for the functions)

To see internal commands

# help

To see external commands

# tab (then answer) y

Knowing how bash finds the commands can be helpful if you want to use
a specific command with a redundant name. For example, maybe
pwd is an internal command and an external command.

The internal command will run unless you specify the external
command, which might be stated like as below in your script.

/usr/bin/pwd

If the command is not found in an alias, function, or internally; bash will
search the PATH for the command.

It will use the PATH statement from left to right.

To see the path statement

echo $PATH

~

User avatar
r1tz
Posts: 162
Joined: Thu 09 Sep 2010, 05:19
Location: In #puppylinux (IRC)

#26 Post by r1tz »

Another useful command is "mkdir -p"
mkdir= Make directory
-p = Make the parent file if it doesn't exist.

So, i want to make a directory /mnt/sda1/lupu52/backup/2010

Code: Select all

mkdir -p /mnt/sda1/lupu52/backup/2010
Instead of making a dir, enter it, make another dir, enter it.

Also, if you keep making some minor typo when doing "cd"

Code: Select all

shopt -s cdspell
This will auto correct some of your mistakes while doing "cd"
----
EDIT
Also, i dunno what the "shift" is for. It is redundant :D
I just thought that i will copy it over... :?
Last edited by r1tz on Mon 07 Mar 2011, 09:56, edited 1 time in total.

Bruce B

#27 Post by Bruce B »

smallfish wrote:This is intended to introduce beginners to the shell
and scripts so that they may begin experiencing the true power of Linux.
Who are you talking to?

You stuck this piece in the middle of some posts I made. I wonder if it
was meant for me. If not, say who you intended it for.

None are going to be programmers without some basic theory. Which is
what I've been presenting. I have plans to move to other areas. But I'm
not there yet.

I'm presuming basic computer skills, knowledge of basic acronyms and a
reading level of an eighth grader.

If you think I went over an eighth grade level, please copy and paste the
text in context. I'd like to see where I went wrong.

If someone else moved at a faster gradient than he should have, copy
and paste and I'll explain at an eighth grade level.

Or for that matter, if you have any questions, ask, people are here to
help.

jamesbond
Posts: 3433
Joined: Mon 26 Feb 2007, 05:02
Location: The Blue Marble

#28 Post by jamesbond »

Bruce B wrote:source r should achieve the same results

When done, delete the file r, it's purpose is served
and I will show you a much better way.

~
Bruce, would you be sharing how to do it in a better way? Image.
I find this thread useful, I didn't know the "help" command exist - I keep referring to the bash reference manual when I need to know how a certain internal command works.
Fatdog64 forum links: [url=http://murga-linux.com/puppy/viewtopic.php?t=117546]Latest version[/url] | [url=https://cutt.ly/ke8sn5H]Contributed packages[/url] | [url=https://cutt.ly/se8scrb]ISO builder[/url]

Bruce B

#29 Post by Bruce B »

jamesbond wrote:
Bruce B wrote:source r should achieve the same results

When done, delete the file r, its purpose is served
and I will show you a much better way.
Bruce, would you be sharing how to do it in a better way?
That is exactly what I mean to do.

In a post or two, you will see.

~

Bruce B

#30 Post by Bruce B »

jamesbond wrote: I didn't know the "help" command exist
I didn't mention once you see the command, then type, according to
examples below:

# help commandname

# help pwd
#for a real example

~

jamesbond
Posts: 3433
Joined: Mon 26 Feb 2007, 05:02
Location: The Blue Marble

#31 Post by jamesbond »

Thanks Bruce. One can always learn new things every day here - even from the Beginner section :D
Fatdog64 forum links: [url=http://murga-linux.com/puppy/viewtopic.php?t=117546]Latest version[/url] | [url=https://cutt.ly/ke8sn5H]Contributed packages[/url] | [url=https://cutt.ly/se8scrb]ISO builder[/url]

Bruce B

#32 Post by Bruce B »

When this topic started, I thought I'd leave others talk about shell
scripting. I'd contribute by teaching how customize the shell with aliases
and functions.

Before making a new command of any kind, make sure the command
name doesn't exist. We are going to make a new command called mnt.
What you would want to do is type in mnt to make sure no such
command already exists.

Enter this on the command line:

# alias mnt='cd /mnt'

Then run mnt. You should now be in the /mnt directory

Then using the command separator ; run the following command:

# mnt;rox

This should open an instance of rox in the /mnt directory. It is faster
and easier than using the rox interface to get there.

~

Bruce B

#33 Post by Bruce B »

Introducing ~/.bashrc

Each time we open a terminal emulator, bash reads /root/.bashrc and
executes all the commands.

Presently, I'm focused on getting us started with aliases to change
directories. Once these aliases have been written into .bashrc, we never
have to enter them again. They become a part of our shell commands,
seamlessly.

I want everything easy. For this reason I use very cryptic commands. I
also try and keep things a bit consistent. Commands to edit files start
with ed

alias edrclocal='mp /etc/rc.d/rc.local'
alias edprofile='mp /etc/profile'

You get the idea, cryptic, but somewhat intuitive.

More lecture on sourcing

.bashrc is sourced when bash opens

Bash programmers sometimes get confused by not understanding what
does and doesn't get carried down, up or sideways to another emulator.

Puppy's /etc/profile sets up the working environment. It is not a shell
script and needs to run at very low level, it runs by sourcing and before
bash even comes into play.

A sourced file is simply a flat text file with commands in it. It doesn't
need to have an executable bit set. It doesn't need #!/bin/bash on the
top line.

For a practice test, make a file with this line.

echo foo bar

Then run the file like this:

. filename


~

Bruce B

#34 Post by Bruce B »

Open ~/.bashrc with a text editor and add the following commands. You
don't need the comments, so delete them as wanted. Make sure to always
leave on linefeed at the end of your file after manually editing.

Code: Select all

# shows full path at prompt
export PS1='[\w] '

# shows current directory
#export PS1='[\W] '

# moves back one directory
alias ..='cd ..'

# moves back two directories
alias ...='cd ../..'

# moves back three directories
alias ....='cd ../../..'

# to return to a saved directory, a script is needed
# but not yet included in this post
alias u='. /tmp/uu~'

# returns to last directory
alias b='cd -'

# refreshes .bashrc
alias rf='. ~/.bashrc'

# opens .bashrc for editing, the resources it
# use text editor of YOUR choice
alias eda='mp ~/.bashrc;. ~/.bashrc'

Changes will take effect on opening the next emulator.

More to come, soon.

~

Bruce B

#35 Post by Bruce B »

I advise keeping all your scripts in their own directory. I use /root/bin

If the directory of your choice doesn't exist, make it.

To add it to the path statement open /etc/profile and find the PATH= line

Add your directory to the end like this :/root/foobar

The script presented here is called acd, it means 'add current directory'
(to .bashrc)

It is a way of bookmarking your favorite directories.

If you are in /usr , then type acd and it will add usr as a command to cd
to /usr


alias usr='cd /usr'

If you are in /usr/lib it will add lib as the command to cd to /usr/lib, you
may not want that as your command name, if not then run the
command like this

acd usrlib

alias usrlib='cd /usr/lib'

If you are in /mnt/sda2, acd will add this command to your .bashrc file

alias sda2='cd /mnt/sda2'

If you want another name, run it like this: acd a2

alias a2='cd /mnt/sda2'

Code: Select all

#!/bin/bash
[ $1 ] && name=$1
[ ! $1 ] && name=`basename $PWD`
echo alias $name="'cd $PWD'">>/root/.bashrc
</root/.bashrc grep "$name"
From here on you can build your command line 'bookmarks' with great
ease. It becomes especially usefully with long directory paths. Look what
the command doors does on my computer.

alias doors='cd /mnt/sdb1/mp3/doors'

Attached is the actual file acd.zip, if you'd rather not make it.

~
Attachments
acd.zip
(236 Bytes) Downloaded 1655 times

Bruce B

#36 Post by Bruce B »

acd (add current directory) explained

Here is the complete script

Code: Select all

#!/bin/bash
[ $1 ] && name=$1
[ ! $1 ] && name=`basename $PWD`
echo alias $name="'cd $PWD'">>/root/.bashrc
</root/.bashrc grep "$name"

#!/bin/bash
  • tells Linux it is a shell script executable
    /bin/bash tells which interpreter I want to use, also its location
[ $1 ] && name=$1
  • [ is a command called test
    a good unix user would not put a command in a filename
    it is little things like what Windows users do that can
    cause us problems with our scripts, unless we know [ is
    an actual command

    $1 is a command line argument or parameter.
    $1 would be the first command
    $2 would be the second command

    ] is not a command. It is syntax used to say "end of test"

    [ $1 ] is simply a way of 'testing' to see of the user entered a command
    line argument

    && is a conditional operator. If the condition is true, it executes the
    command on the right, if false nothing happens

    name is a variable. The = sign is the end of the variable. Anything to the
    right of the = sign gets moved into the variable

    If I entered the text foobar on the command line, after the executable
    name, then $1 would be true and the variable name would contain the
    text foobar
[ ! $1 ] && name=`basename $PWD`
  • Either I entered text on the command line or I didn't.

    ! is an operator which means not

    [ ! $1 ] tests to see if not $1 - in English it asks if I did not enter a
    parameter.

    If I didn't then a true condition exists and the operator && will execute
    the command on its right.

    name=`basename $PWD`

    name is as already explained a variable, it can contain a variety of data,
    the data in it is not static.

    $PWD is an environment variable. It changes its contents to match our
    current directory.

    If we were in /usr/lib/firefox then $PWD would contain the data /usr/lib
    /firefox

    If we typed basename $PWD on the command line it would echo firefox

    In this usage, basename strips out the parent directories

    We want to move, shove the output of basename $PWD into our variable,
    this is where the backticks come in. We need them in order to force the
    output from right to left into the variable.
echo alias $name="'cd $PWD'">>/root/.bashrc
  • echo means to repeat and is a very common command

    our goal here is to stuff the following command at the tail of .bashrc

    alias firefox='cd /usr/lib/firefox'


    name and PWD are both initialized variables

    We don't want the variables, we want the data they contain. To
    accomplish this we add the $ to the front of the variable.

    echo $PWD would print /usr/lib/firefox
    echo $name would print firefox

    I need the single quotes in the command I want to write to .bashrc

    The single quote also has a meaning and prevents the expansion I need,
    but using the double-quotes allows it.

    Let's look at the command again:

    echo alias $name="'cd $PWD'">>/root/.bashrc

    I do not want the command printed to the screen, also known as standard
    output, I want it printed to the file /root/.bashrc

    The >> redirects the output to where I send it, which is /root/.bashrc

    The >> appends the file

    A > would delete all existing data in .bashrc and leave me only with the
    command.

    >, >> and < are called redirection symbols, they are instructions to
    redirect output
</root/.bashrc grep "$name"
  • The < redirects the entire /root/.bashrc file to grep

    grep is a search utility, as the data is being redirected through grep, it
    searches for the contents of $name which is firefox, in our example.

    All lines containing 'firefox' will be displayed to standard output, our
    monitor.

    Its purpose is merely to verify that the command acd did what we wanted.
Code repeated, does it make more sense now? I hope!

Code: Select all

#!/bin/bash
[ $1 ] && name=$1
[ ! $1 ] && name=`basename $PWD`
echo alias $name="'cd $PWD'">>/root/.bashrc
</root/.bashrc grep "$name"
~

Bruce B

#37 Post by Bruce B »

From the commands I made to put into .bashrc

alias u='. /tmp/uu~'

In this post contains the support script.

Code: Select all

#!/bin/bash
echo cd $PWD>/tmp/uu~
The script name is uu - when we want to save a directory for fast access
later, type uu.

To return to the directory, at any time, type u

It is attached as uu.zip if you'd rather have it that way.

There are also two builtin commands pushd and popd, these can be very
useful in scripts, but not often used, because not often needed. I leave
the user to learn about them.

help pushd
help popd


~
Attachments
uu.zip
second uu.zip upload - this points to /tmp, the first pointed to /dev/shm
download the new one if you downloaded the /dev/shm one
(170 Bytes) Downloaded 1684 times
Last edited by Bruce B on Tue 08 Mar 2011, 09:37, edited 1 time in total.

Bruce B

#38 Post by Bruce B »

Often when we make a directory, we want to change to the newly made
directory.

As the reader has learned by now there are many, many ways to make
life easier by using the command line.

I want to show an example of how to add a function to your .bashrc file.

This function will make and new directory and change to the newly made
directory.

Code: Select all

ndir() {

    if [ $1 ] ; then
        [ ! -d $1 ] && mkdir $1
        cd $1
    else
        echo Missing argument
    fi

}
To use you would type in

ndir foobar

You can also add more commands by using the ;

ndir foobar;rox

Functions can be defined in a few different ways. The example above
shows how I do it. Here is a template

Code: Select all

functionname() {

    echo

}
There has to be a command of some sort or bash will get mad at you, so
for the template, I used echo.

~

Bruce B

#39 Post by Bruce B »

When to use .bashrc and when to use scripts.

When you run a script, your .bashrc aliases and functions are not
available in the script. This is usually, if not always, to your advantage.
You don't want some alias you forgot about interfering with your script.

Here is an example:

alias rm='rm -i'


This alias means that you will be asked to verify each deletion.

You may not want that interaction in your script, considering the aliases
don't exist, you use the rm command as you want without interference.
Your script will behave as written.

Some distributions add the .bashrc commands below by default,
considering how hard it is to undo mistakes, I recommend the aliases
below.

BTW - we are done with the change directory instructions.

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'

This will cause an interactive command where you have to confirm the
actions.

Suppose you know you want to remove every file in a directory and don't
want to confirm everyone, you can escape the alias with a backslash

\rm *


Here is another example of aliases I use

alias xms='xmms *.mp3 &'


Remember 'doors' does cd /mnt/sda2/mp3/doors

As fast as I can type doors;xms, the music I want to play starts playing.
This is more convenient than the mouse movements required to open
xmms and do the same thing.

Also, I could have an alias like this:

alias playdoors='xmms /mnt/sda2/mp3/doors/*.mp3 &'


or

alias playdoors='cd /mnt/sda2/mp3/doors;xmms *.mp3 &'

~

Bruce B

#40 Post by Bruce B »

Sometimes your .bashrc file can become very large. I decided to give a
command which will allow you to easily search it.

alias grepbashrc='<~/.bashrc grep -i'

[~] grepbashrc usr
alias usrbin='cd /usr/bin'
alias usrlib='cd /usr/lib'
alias usr='cd /usr'
alias usrlocal='cd /usr/local'
alias usrlocalbin='cd /usr/local/bin'
alias usrshare='cd /usr/share'

Here I refine the search results by piping again through grep

[~] grepbashrc usr | grep local
alias usrlocal='cd /usr/local'
alias usrlocalbin='cd /usr/local/bin'
[~]

The general rule is, you can add commands to your alias, this is
demonstrated above.

Shell expansion within the alias itself is, well, not beginning level stuff.

If you need to expand variables, the function is the better choice.

~

Post Reply