The Text-User Interface
Chapter 49 - Eliminating trailing white space
I had a lengthy script, which ran very successfully. I modified it from time to time. Then one little change and it stopped running. I went over and over the change and couldn't find a thing.
I went over every aspect of the script and still could not find the trouble. I opened it with a hex editor to view things which a text editor wouldn't show and still didn't find the cause.
I eventually thought maybe if it wasn't anywhere in the printing characters, it was likely a problem caused by non printing characters.
In the vast majority of cases when your scripts don't do as intended the problem is in the printing characters. The problem I describe is very rare and maybe shouldn't even be mentioned . . .
. . .but I suppose if it happened to me, it might happen to you. Also, one thing we have very little use for in our scripts, text documents and web pages is trailing white space.
The only files we ever want to remove trailing white space on are text files. Scripts, and html files are text files.
For starters in building this script, let's see how to tell if the intended file is an actual text file. file will tell it if it is.
file index.html, says: HTML document text
file updatedb, says: Bourne-Again shell script text executable
we can use grep's return code to see if it is safe to remove trailing spaces
~~~~~~~~~~~~~~
line 1 : file $1 | grep " text" >/dev/null
line 2 : [ x$? = x0 ] && echo $1 is a text file
line 1 : file processes the file in $1, we pipe the output to grep, grep looks for this text string" file" and we redirect the output to the black hole >/dev/null
grep gave bash an invisible return code based on if it found the string " file", we use the return code in line 2
line 2 : we test the return code to see if it matches 0. Earlier I showed arithmetic comparison operators. The = is not for arithmetic, it's more for string comparisons. When making comparisons we never want to compare one string with a blank. By using the x, either side of the string comparison are assured of having some kind of value as a place holder.
~~~~~~~~~~~~~~
String comparison - not arithmetic
Does x0 == x0 ? If true it is a text file
Earlier I used quotes, like this:
[ "$?" = "0" ] && echo $1 is a text file
The quotes serve the same purpose as the x - you're developing you own style.
We will work more on our script in the next chapter
~
Chapter 49 - eliminating trailing white space
I had a lengthy script, which ran very successfully. I modified it from time to time. Then one little change and it stopped running. I went over and over the change and couldn't find a thing.
I went over every aspect of the script and still could not find the trouble. I opened it with a hex editor to view things which a text editor wouldn't show and still didn't find the cause.
I eventually thought maybe if it wasn't anywhere in the printing characters, it was likely a problem caused by non printing characters.
In the vast majority of cases when your scripts don't do as intended the problem is in the printing characters. The problem I describe is very rare and maybe shouldn't even be mentioned . . .
. . .but I suppose if it happened to me, it might happen to you. Also, one thing we have very little use for in our scripts, text documents and web pages is trailing white space.
The only files we ever want to remove trailing white space on are text files. Scripts, and html files are text files.
For starters in building this script, let's see how to tell if the intended file is an actual text file. file will tell it if it is.
file index.html, says: HTML document text
file updatedb, says: Bourne-Again shell script text executable
we can use grep's return code to see if it is safe to remove trailing spaces
~~~~~~~~~~~~~~
line 1 : file $1 | grep " text" >/dev/null
line 2 : [ x$? = x0 ] && echo $1 is a text file
line 1 : file processes the file in $1, we pipe the output to grep, grep looks for this text string" file" and we redirect the output to the black hole >/dev/null
grep gave bash an invisible return code based on if it found the string " file", we use the return code in line 2
line 2 : we test the return code to see if it matches 0. Earlier I showed arithmetic comparison operators. The = is not for arithmetic, it's more for string comparisons. When making comparisons we never want to compare one string with a blank. By using the x, either side of the string comparison are assured of having some kind of value as a place holder.
~~~~~~~~~~~~~~
String comparison - not arithmetic
Does x0 == x0 ? If true it is a text file
Earlier I used quotes, like this:
[ "$?" = "0" ] && echo $1 is a text file
The quotes serve the same purpose as the x - you're developing you own style.
We will work more on our script in the next chapter
~
Chapter 49 - eliminating trailing white space
Chapter 50 - Introducing 'notrail'
notrail strips trailing tabs and spaces from text documents. This includes scripts and html files. It also saves the originals
sed
A new utility introduced here is 'sed', a stream editor. You won't learn it overnight, but you will learn it in time. Try and not be overly anxious with this one.
I've provide some support material for you
A link from where I got the snippet used in this script, Handy one liners for sed
Also, use the forum search to see how others have used sed.
~
Please download in install attachment notrail
Edited: Attachment removed for a better utility, see Chapter 80 and download cleanf.zip
Chapter 50 - Introducing 'notrail'
notrail strips trailing tabs and spaces from text documents. This includes scripts and html files. It also saves the originals
Code: Select all
#!/bin/bash
main() {
var "$@"
process "$@"
}
var() {
[ ! $1 ] && echo "missing filespec" && exit
savedir=/var/notrail
[ ! -d $savedir ] && mkdir $savedir
subdir=`date "+%Y%m%d-%H%M"`
savedir=${savedir}/$subdir
[ ! -d $savedir ] && mkdir ${savedir}
[ ! -d $savedir ] && echo "$savedir doesn't exist, exiting" && exit
logfile="${savedir}/LOG_FILE.LOG"
}
process() {
echo "Working, please wait . . ."
for i in "$@" ; do
[ ! -f $i ] && continue
file $i | grep text >/dev/null
if [ "$?" == "0" ] ; then
mv $i $savedir
<${savedir}/$i sed 's/[ \t]*$//'>$i
echo "Cleaned $i" >> $logfile
else
echo "$i not a text file">>$logfile
fi
done
echo
echo "Original files saved in $savedir"
echo "Directory contents: "
ls $savedir
}
main "$@"
A new utility introduced here is 'sed', a stream editor. You won't learn it overnight, but you will learn it in time. Try and not be overly anxious with this one.
I've provide some support material for you
A link from where I got the snippet used in this script, Handy one liners for sed
Also, use the forum search to see how others have used sed.
~
Please download in install attachment notrail
Edited: Attachment removed for a better utility, see Chapter 80 and download cleanf.zip
Chapter 50 - Introducing 'notrail'
Last edited by Bruce B on Tue 04 Aug 2009, 08:34, edited 1 time in total.
Chapter 51 - I really want to keep these chapters moving. Lots more to come.
I've been down sick bad. Apart from finding energy when sick, the creative aspects needed aren't there when I want them.
I want you to know I'm still with it.
-----------------
If any have questions, or problems, please PM me.
I've been down sick bad. Apart from finding energy when sick, the creative aspects needed aren't there when I want them.
I want you to know I'm still with it.
-----------------
If any have questions, or problems, please PM me.
Chapter 51 - swapf
Guess what we are going to do? That's right. Make another script.
Hint: If you haven't noticed by now, the way to learn how to script and program, is by scripting and programming. You just need a few people to help you get started.
Some times we want to swap files, one file with the other. It takes about three command line operations. If for purpose of testing you swap back and forth a few times, it takes several commands.
The basic command line ( and program flow is like this )
rename file A to a non existent name
rename file B to file A's original name
rename, the renamed file A to the original name of file B
We already learned it's good to have some sanity and error checking, and it's good to have some on screen feed back.
When a command prompt merely returns, without feedback, it leaves sort of a feeling of a vacuum, did it do like we wanted? With good screen feedback, any wondering is diminished greatly.
~~~~~~~~~~
We now have a rough idea what we want our script to do. (0) give a short yet descriptive name, (1) swap file names, (2) do some error checking before doing the swap, (3) give us on screen feed back.
This is an easy script, so lets get started
SCRIPT OUTLINE
Note what I did above, was put everything I want my script to do according to descriptive functions. All I have to do is fill out some simple commands in the appropriate functions, watch how easy it is. Even complex programming can be simple when broken down into small parts.
The actual script
Script notes and comments
We could name Windows spaced files, but I don't want to in this script.
$$ is the pid of the child process
If $1 is busybox, (as an example), it gets named like this: busybox.3189, odds are extremely in our favor no such file name exists. Extra insurance is the use of mv's -i (--interactive) switch to prevent an unintentional overwrite.
When we want to use a command line argument such as $1 or $2 we need to pass it to each function which uses it. Or set an internal variable, which we didn't do in this example.
With the on screen feedback, you can easily verify the files were swapped properly by comparing the before and after times, dates and sizes and relative positions on the screen.
Note: your functions can be called in any order main says. The 'after' function came before the 'swapem' : it doesn't matter.
~
Chapter 51 - swapf
Instructions: download and install the attached script, if you want it.
Guess what we are going to do? That's right. Make another script.
Hint: If you haven't noticed by now, the way to learn how to script and program, is by scripting and programming. You just need a few people to help you get started.
Some times we want to swap files, one file with the other. It takes about three command line operations. If for purpose of testing you swap back and forth a few times, it takes several commands.
The basic command line ( and program flow is like this )
rename file A to a non existent name
rename file B to file A's original name
rename, the renamed file A to the original name of file B
We already learned it's good to have some sanity and error checking, and it's good to have some on screen feed back.
When a command prompt merely returns, without feedback, it leaves sort of a feeling of a vacuum, did it do like we wanted? With good screen feedback, any wondering is diminished greatly.
~~~~~~~~~~
We now have a rough idea what we want our script to do. (0) give a short yet descriptive name, (1) swap file names, (2) do some error checking before doing the swap, (3) give us on screen feed back.
This is an easy script, so lets get started
SCRIPT OUTLINE
Code: Select all
main() {
}
vars() {
}
before() {
}
after() {
}
swapem() {
}
main $1 $2
The actual script
Code: Select all
#!/bin/bash
main() {
vars $1 $2
before $1 $2
swapem $1 $2
after $1 $2
}
vars() {
[ ! $2 ] && echo "Insufficient arguments" && exit
[ ! -f $1 ] && echo "Filename $1 doesn't exist, exiting" && exit
[ ! -f $2 ] && echo "Filename $2 doesn't exist, exiting" && exit
echo $1 | grep " ">/dev/null
[ x$? = x0 ] && echo "Come on, spaces in file names are for Windows users" && exit
echo $2 | grep " ">/dev/null
[ x$? = x0 ] && echo "Come on, spaces in file names are for Windows users" && exit
}
before() {
echo ""
echo "Before swapping filenames:"
ls -l $1
ls -l $2
echo ""
}
after() {
echo "After swapping filenames:"
ls -l $1
ls -l $2
echo ""
}
swapem() {
mv -i $1 $1.$$
mv -i $2 $1
mv -i $1.$$ $2
}
main $1 $2
We could name Windows spaced files, but I don't want to in this script.
$$ is the pid of the child process
If $1 is busybox, (as an example), it gets named like this: busybox.3189, odds are extremely in our favor no such file name exists. Extra insurance is the use of mv's -i (--interactive) switch to prevent an unintentional overwrite.
When we want to use a command line argument such as $1 or $2 we need to pass it to each function which uses it. Or set an internal variable, which we didn't do in this example.
With the on screen feedback, you can easily verify the files were swapped properly by comparing the before and after times, dates and sizes and relative positions on the screen.
Note: your functions can be called in any order main says. The 'after' function came before the 'swapem' : it doesn't matter.
~
Chapter 51 - swapf
Instructions: download and install the attached script, if you want it.
- Attachments
-
- swapf.zip
- (445 Bytes) Downloaded 1241 times
Chapter 52 - more grep
I noted this question in the beginners section,
If we understand that the directory /etc mainly holds system configuration information, we have a good place to start looking.
We would want to find out which files have the word puppypc in them to get an idea where to make the changes we want to make. Here is some practice using grep on the command line.
cd /etc : stay in this directory for the exercises below
grep puppypc * : look in all files, case sensitive search, display instances with file names
grep -i puppypc * : look in all files, case insensitive search, display instances with file names
grep -il * : as above but display only the file names
grep -r puppypc * : search in subdirectories also
or
grep -R puppypc * : search in subdirectories also
grep -ilr puppypc * : is valid, meaning we can mix our switches
Please practice these commands. The command line user needs to be well versed with the basics and intermediate usage of grep.
The examples I gave above use the short switches, which is what we mainly use on the command line. In scripts the long hand makes the script easier to read and we only type the script commands one time, (hopefully). Although short switches are frequently used in scripts, but it's a nice practice to use long names.
Short and long switches used in this chapter for examples
-i , --ignore-case
-r , --recursive
-R , --recursive
-l , --files-with-matches
~
Chapter 52 - more grep
I noted this question in the beginners section,
- "I can't find an easy way to change the computer name, I can view it in the system information viewer but cant find how to change the details."
If we understand that the directory /etc mainly holds system configuration information, we have a good place to start looking.
We would want to find out which files have the word puppypc in them to get an idea where to make the changes we want to make. Here is some practice using grep on the command line.
cd /etc : stay in this directory for the exercises below
grep puppypc * : look in all files, case sensitive search, display instances with file names
grep -i puppypc * : look in all files, case insensitive search, display instances with file names
grep -il * : as above but display only the file names
grep -r puppypc * : search in subdirectories also
or
grep -R puppypc * : search in subdirectories also
grep -ilr puppypc * : is valid, meaning we can mix our switches
Please practice these commands. The command line user needs to be well versed with the basics and intermediate usage of grep.
The examples I gave above use the short switches, which is what we mainly use on the command line. In scripts the long hand makes the script easier to read and we only type the script commands one time, (hopefully). Although short switches are frequently used in scripts, but it's a nice practice to use long names.
Short and long switches used in this chapter for examples
-i , --ignore-case
-r , --recursive
-R , --recursive
-l , --files-with-matches
~
Chapter 52 - more grep
Chapter 53 - colorful prompts
Here's the command list for file, title: ps1colors
Its obvious purpose is to change our prompt colors on the fly. A not obvious purpose is I plan do something with colorful prompts in a future lesson.
Remembering from previous lessons, there are some things we can't easily do in a 'child shell', this is one of them. If we changed our prompt colors in a child shell, the colors would change and then return to the previous state when the child exits.
Also, the 'export' command (which hasn't been discussed) doesn't work like we'd think it should in an X window terminal emulator.
FYI : The variable PS1 would mean to say - this is for our primary prompt.
The data in these variables would be hard to read without understanding bash' escape sequences and having an ASCII color chart on hand.
We can change prompt colors on the fly from the command line, but because we can't easily do it in a child shell, we run the commands by 'sourcing'.
Sourcing has been discussed earlier, but I hardly think it hurts to discuss it a little more. One reason why, is: Some of the scripting tutorials you will find online and study, barely scratch the surface of sourcing.
We use this alias: alias ps1='source /root/bin/ps1colors'
To install:
copy and paste the alias in two files, (1) /etc/profile.local , (2) /root/.bashrc
unzip ps1colors to /root/bin
To run:
I've made it pretty easy, you type lowercase ps1 and the first three letters of the color you want. If you type only ps1 you will get onscreen help
ps1 blu
ps1 cya
ps1 red
Please consider this required for an upcoming lesson. And I hope you have fun using it in the meantime.
~
Chapter 53 - colorful prompts
Here's the command list for file, title: ps1colors
Code: Select all
case $1 in
nor*) export PS1='[\w] ' ;; # normal
bla*) export PS1='\[\e[1;30m\][\w]\e[0m\] ' ;; # black
whi*) export PS1='\[\e[1;37m\][\w]\e[0m\] ' ;; # white
red*) export PS1='\[\e[1;31m\][\w]\e[0m\] ' ;; # red
gre*) export PS1='\[\e[1;32m\][\w]\e[0m\] ' ;; # green
blu*) export PS1='\[\e[1;34m\][\w]\e[0m\] ' ;; # blue
cya*) export PS1='\[\e[1;36m\][\w]\e[0m\] ' ;; # cyan
mag*) export PS1='\[\e[1;35m\][\w]\e[0m\] ' ;; # magenta
yel*) export PS1='\[\e[1;33m\][\w]\e[0m\] ' ;; # yellow
*) echo "Usage:"
echo "ps1 <nor|bla|whi|red|gre|blu|cya|mag|yel>" ;; # help
esac
Remembering from previous lessons, there are some things we can't easily do in a 'child shell', this is one of them. If we changed our prompt colors in a child shell, the colors would change and then return to the previous state when the child exits.
Also, the 'export' command (which hasn't been discussed) doesn't work like we'd think it should in an X window terminal emulator.
FYI : The variable PS1 would mean to say - this is for our primary prompt.
The data in these variables would be hard to read without understanding bash' escape sequences and having an ASCII color chart on hand.
We can change prompt colors on the fly from the command line, but because we can't easily do it in a child shell, we run the commands by 'sourcing'.
Sourcing has been discussed earlier, but I hardly think it hurts to discuss it a little more. One reason why, is: Some of the scripting tutorials you will find online and study, barely scratch the surface of sourcing.
We use this alias: alias ps1='source /root/bin/ps1colors'
To install:
copy and paste the alias in two files, (1) /etc/profile.local , (2) /root/.bashrc
unzip ps1colors to /root/bin
To run:
I've made it pretty easy, you type lowercase ps1 and the first three letters of the color you want. If you type only ps1 you will get onscreen help
ps1 blu
ps1 cya
ps1 red
Please consider this required for an upcoming lesson. And I hope you have fun using it in the meantime.
~
Chapter 53 - colorful prompts
- Attachments
-
- ps1colors.zip
- (365 Bytes) Downloaded 1145 times
Chapter 54 - Minimum Profit configuration file
Optional
Puppy gives us an excellent text editor, Minimum Profit. (mp). And, as command line users, we want lots of good applications.
Minimum Profit (mp) has a highly configurable rc file. I've written an rc file which I think you will like better than the default configuration file.
The name of the file is /root/.mprcx
, but it needs to be /root/.mprc to be recognized and used by mp.
To install it download mprc.zip to /root and unzip it. You may not see the .mprcx file, because it is a 'hidden' file.
Then use your swapf utility from an earlier chapter and run this command:
swapf .mprc .mprcx
You can run the same command over and over to swap the configuration files to see which you like best. Also, you can modify the files.
If you want to use mc as your default Midnight Commander editor
F9 -> Options -> Configuration . . . -> uncheck 'use internal edit', then Save
~
Chapter 54 - Minimum Profit configuration file
Optional
Puppy gives us an excellent text editor, Minimum Profit. (mp). And, as command line users, we want lots of good applications.
Minimum Profit (mp) has a highly configurable rc file. I've written an rc file which I think you will like better than the default configuration file.
The name of the file is /root/.mprcx
, but it needs to be /root/.mprc to be recognized and used by mp.
To install it download mprc.zip to /root and unzip it. You may not see the .mprcx file, because it is a 'hidden' file.
Then use your swapf utility from an earlier chapter and run this command:
swapf .mprc .mprcx
You can run the same command over and over to swap the configuration files to see which you like best. Also, you can modify the files.
If you want to use mc as your default Midnight Commander editor
F9 -> Options -> Configuration . . . -> uncheck 'use internal edit', then Save
~
Chapter 54 - Minimum Profit configuration file
- Attachments
-
- mprc.zip
- (3.91 KiB) Downloaded 1167 times
Chapter 55 - an automated e2fsck (part 1)
If you don't have Linux partitions, you can't do this exercise. I intend it to become a Puppy portable script for automatically checking ext2 and ext3 partitions.
Here is a portion.
Notes:
This script will do nothing, at first, because the commands in main have # before the commands. To run a function or multiple of functions remove the #
The only function we need is the last one, it does it all. But in the event it is not apparent to you want it does, the logic which builds up to it is displayed in the previous functions.
Exercise:
Copy and paste the code to a practice script. Experiment with it by removing and reinserting the comments in main. Try and understand exactly what we are doing. Namely piping utilities to utilities, until we have exactly the data we need for the latter parts of or our script.
Note also, the script is (and will be) portable, it should run on any Puppy computer. The reason I say 'Puppy' is because some Linux don't let us run root easily and fdisk is a root command.
Note: although not common practice, you can be very descriptive with function names.
We'll work on the script some more, in upcoming lessons.
~
Chapter 55 - an automated e2fsck (part 1)
If you don't have Linux partitions, you can't do this exercise. I intend it to become a Puppy portable script for automatically checking ext2 and ext3 partitions.
Here is a portion.
Code: Select all
#!/bin/bash
main() {
# getlist_of_partitions
# getlist_of_linux_partitions
# cut_first_field_from_list
# put_list_into_one_line
# put_one_line_list_into_variable
}
getlist_of_partitions() {
echo "function: getlist_of_partitions"
echo ""
fdisk -l
}
getlist_of_linux_partitions() {
echo ""
echo "function: getlist_of_linux_partitions"
echo ""
fdisk -l | grep "83 Linux"
}
cut_first_field_from_list() {
echo ""
echo "function: cut_first_field_from_list"
echo ""
fdisk -l | grep "83 Linux" | cut -d " " -f 1
}
put_list_into_one_line() {
echo ""
echo "function: put_list_into_one_line"
echo ""
fdisk -l | grep "83 Linux" | cut -d " " -f 1 | tr "\n" " "
echo " " # for on screen formatting only
}
put_one_line_list_into_variable() {
echo ""
echo "function: put_one_line_list_into_variable"
echo ""
partitions=`fdisk -l | grep "83 Linux" | cut -d " " -f 1 | tr "\n" " "`
# display data in variable
echo "variable \"partitions\" contents: $partitions"
}
main
This script will do nothing, at first, because the commands in main have # before the commands. To run a function or multiple of functions remove the #
The only function we need is the last one, it does it all. But in the event it is not apparent to you want it does, the logic which builds up to it is displayed in the previous functions.
Exercise:
Copy and paste the code to a practice script. Experiment with it by removing and reinserting the comments in main. Try and understand exactly what we are doing. Namely piping utilities to utilities, until we have exactly the data we need for the latter parts of or our script.
Note also, the script is (and will be) portable, it should run on any Puppy computer. The reason I say 'Puppy' is because some Linux don't let us run root easily and fdisk is a root command.
Note: although not common practice, you can be very descriptive with function names.
We'll work on the script some more, in upcoming lessons.
~
Chapter 55 - an automated e2fsck (part 1)
Chapter 56 - hexedit
Part of building a good text user interface is having plenty of good TUI applications. Attached to this post is [N]Curses Hexedit 0.9.7 by Adam Rogoyski
There might be a slightly newer version available, than the one attached. (It compiled very easily in Puppy.)
http://www.rogoyski.com/adam/programs/hexedit
http://packages.qa.debian.org/n/ncurses-hexedit.html
The man page is converted to html
The info page can be read with a text editor
----
Puppy has an editor of the same name, rename it to a different name. The reason for the replacement is because this editor is so much easier to work with. Until you reboot, you may have to run it by full path.
Enjoy
~
Chapter 56 - hexedit
Part of building a good text user interface is having plenty of good TUI applications. Attached to this post is [N]Curses Hexedit 0.9.7 by Adam Rogoyski
There might be a slightly newer version available, than the one attached. (It compiled very easily in Puppy.)
http://www.rogoyski.com/adam/programs/hexedit
http://packages.qa.debian.org/n/ncurses-hexedit.html
Code: Select all
Archive: hexedit.zip
Length Date Time Name
-------- ---- ---- ----
24180 07-18-09 14:05 hexedit
12256 07-18-09 14:04 hexedit.1.html
27013 07-18-09 14:03 hexedit.info
-------- -------
63449 3 files
The man page is converted to html
The info page can be read with a text editor
----
Puppy has an editor of the same name, rename it to a different name. The reason for the replacement is because this editor is so much easier to work with. Until you reboot, you may have to run it by full path.
Enjoy
~
Chapter 56 - hexedit
- Attachments
-
- hexedit.zip
- (25.5 KiB) Downloaded 1163 times
Chapter 57 - more about loops
I knew a fellow who while studying beginning C, couldn't for the life of him grasp the reason for using loops in programming.
In this example, I hope to make it very clear why we may want to use loops. As an additional bonus, I wish to show how we can make it look as if we are doing arithmetic when all we are doing is echoing arguments.
What we are looking at are three 'for loops' - nested. Nesting is a word and a concept the new programmer needs to become familiar with.
The indents help us easily identify where the nesting occurs.
This simple routine will count from 000 to 999 much, much faster, than if we used arithmetic to do it.
If we wanted to do the same thing without loops we would need 1000 lines to do what we can do with 8 lines.
Main thing in this chapter is understand what is presented, and of course feel free to copy, paste, play and practice.
~
Chapter 57 - more about loops
PS If you didn't catch the flow in the loops, try these:
and
And your own variants, until you really do understand.
I knew a fellow who while studying beginning C, couldn't for the life of him grasp the reason for using loops in programming.
In this example, I hope to make it very clear why we may want to use loops. As an additional bonus, I wish to show how we can make it look as if we are doing arithmetic when all we are doing is echoing arguments.
Code: Select all
#!/bin/bash
for i in 0 1 2 3 4 5 6 7 8 9 ; do
for x in 0 1 2 3 4 5 6 7 8 9 ; do
for z in 0 1 2 3 4 5 6 7 8 9 ; do
echo $i$x$z
done
done
done
The indents help us easily identify where the nesting occurs.
This simple routine will count from 000 to 999 much, much faster, than if we used arithmetic to do it.
If we wanted to do the same thing without loops we would need 1000 lines to do what we can do with 8 lines.
Main thing in this chapter is understand what is presented, and of course feel free to copy, paste, play and practice.
~
Chapter 57 - more about loops
PS If you didn't catch the flow in the loops, try these:
Code: Select all
for i in a b c d ; do
for x in 1 2 3 4 ; do
echo $i$x
done
done
Code: Select all
for x in 1 2 3 4 ; do
for i in a b c d ; do
echo $x$i
done
done
Chapter 58 - guess
Thousands of files, I forget the name, but I'm going to use tab completion to help remember. I remembered it started with the letters g-u-e-s-s
Here is where tab completion comes in and makes life easier for us command line users. I typed in the letters I remembered then hit the tab key which filled in the rest, the filename I want is guess_fstype.
We can almost tell what this file does by its name, which is a bit unusual for Linux. Let's see what more we can learn, before putting it to work.
which guess_fstype tells me it's at /sbin/guess_fstype
How does an sbin directory differ from a bin directory? It is a clue that only root can use the file. Think supervisorbin
Let's learn more
cd /sbin
file guess_fstype tells me it's an ELF 32-bit file. Meaning it's compiled and not human readable. So, next step is check help;
guess_fstype --help (results are nothing)
guess_fstype -h (results are nothing)
I want to see the text inside this non-human readable file
<guess_fstype strings
I've just learned a lot, by using strings, among other things, the filesystems it's designed to guess. I won't post the results in this post, because of lots of output.
Do it as your own exercise please, you want to know and understand the file strings.
I searched linux.die.net for a man page and found nothing.
I typed in;
guess_fstype /dev/hda2 and it returned ext3
This is about how I'd have guessed it would work and all I really need to know.
In chapter 55 we came up with this pipe string to put all our Linux partitions into a variable.
partitions=`fdisk -l | grep "83 Linux" | cut -d " " -f 1 | tr "\n" " "`
Linux data partitions are type 83, but not all Linux data partitions are ext2 or ext3. We will use guess_fstype to verify that the partition we intend to check is indeed an ext2 or ext3.
Our testing and repair tool e2fsck has its own built in error checking, so we won't get into trouble as far as data damage.
Nevertheless, I want us to do our own conditional checking and branching when we know we cannot predict the conditions and some checking is in order. In this case, we can't predict our 'customer' isn't using reisferfs, ext4, or something else. Let's do appropriate checking for her.
Script notes: Please note how I placed the curly braces {}, in a different position than in previous lessons.
It is important? The answer is; potentially very important. We you start programming on teams with another or others, do it the way they do it, if you can. You will get along better when working on the same programs with others, and some programmers have very strong feelings about style.
I made a script called showtype and attached it to this post. If you have Linux partitions, please download it, run it and study it. If you don't have Linux partitions, the script is of no value to you.
~
Chapter 58 - guess
Thousands of files, I forget the name, but I'm going to use tab completion to help remember. I remembered it started with the letters g-u-e-s-s
Here is where tab completion comes in and makes life easier for us command line users. I typed in the letters I remembered then hit the tab key which filled in the rest, the filename I want is guess_fstype.
We can almost tell what this file does by its name, which is a bit unusual for Linux. Let's see what more we can learn, before putting it to work.
which guess_fstype tells me it's at /sbin/guess_fstype
How does an sbin directory differ from a bin directory? It is a clue that only root can use the file. Think supervisorbin
Let's learn more
cd /sbin
file guess_fstype tells me it's an ELF 32-bit file. Meaning it's compiled and not human readable. So, next step is check help;
guess_fstype --help (results are nothing)
guess_fstype -h (results are nothing)
I want to see the text inside this non-human readable file
<guess_fstype strings
I've just learned a lot, by using strings, among other things, the filesystems it's designed to guess. I won't post the results in this post, because of lots of output.
Do it as your own exercise please, you want to know and understand the file strings.
I searched linux.die.net for a man page and found nothing.
I typed in;
guess_fstype /dev/hda2 and it returned ext3
This is about how I'd have guessed it would work and all I really need to know.
In chapter 55 we came up with this pipe string to put all our Linux partitions into a variable.
partitions=`fdisk -l | grep "83 Linux" | cut -d " " -f 1 | tr "\n" " "`
Linux data partitions are type 83, but not all Linux data partitions are ext2 or ext3. We will use guess_fstype to verify that the partition we intend to check is indeed an ext2 or ext3.
Our testing and repair tool e2fsck has its own built in error checking, so we won't get into trouble as far as data damage.
Nevertheless, I want us to do our own conditional checking and branching when we know we cannot predict the conditions and some checking is in order. In this case, we can't predict our 'customer' isn't using reisferfs, ext4, or something else. Let's do appropriate checking for her.
Code: Select all
#!/bin/bash
main()
{
variables
partition_types
}
variables()
{
partitions=`fdisk -l | grep "83 Linux" \
| cut -d " " -f 1 | tr "\n" " "`
}
partition_types()
{
for i in $partitions ; do
echo -n " This Linux partition $i is type: "
guess_fstype $i
done
}
main
Code: Select all
before() {
echo
}
Code: Select all
this_example()
{
echo
}
I made a script called showtype and attached it to this post. If you have Linux partitions, please download it, run it and study it. If you don't have Linux partitions, the script is of no value to you.
~
Chapter 58 - guess
- Attachments
-
- showtype.zip
- Shows Linux partitions and format type
- (329 Bytes) Downloaded 1146 times
Chapter 59 - more building our Linux partition checking utility
Puppy doesn't come with much for automatically checking our filesystems. This is cool, because it makes for a good exercise and gives an opportunity to build some useful utilities.
I want to build this utility with you step-by-step, so when we are done, we really understand what we have done.
So far, we've learned (1) how to locate Linux partitions and (2) how to identify the partition type.
We don't want to run our filesystem repair utility on a mounted partition, in this chapter we will learn how to tell if a partition is mounted.
Two files carry this information, (1) /etc/mtab and (2) /proc/mounts.
I use /proc/mounts to test for mounted filesystems.
I'd like you first to look at /proc/mounts; this command;
cat /proc/mounts
Suppose we want to know if /dev/hda1 or /dev/sda1 is mounted, we could use grep capabilities. Here's a fun little script.
Your arguments will be the device name or the mount point, and if you give bad arguments, you can get false positives. But we won't do that in our final script.
We could modify the script to say if or if not mounted, using the if;then statement
We could modify our script to accept more arguments
The purpose of this lesson is to introduce you to how we will check if a partition to be checked is mounted. That is all.
If you have grasped the file /proc/mounts, grep and its return code and how we will use it, you have grasped the meaning of this lesson.
Test and use the scripts as you please.
~
Chapter 59 - more building our Linux partition checking utility
Puppy doesn't come with much for automatically checking our filesystems. This is cool, because it makes for a good exercise and gives an opportunity to build some useful utilities.
I want to build this utility with you step-by-step, so when we are done, we really understand what we have done.
So far, we've learned (1) how to locate Linux partitions and (2) how to identify the partition type.
We don't want to run our filesystem repair utility on a mounted partition, in this chapter we will learn how to tell if a partition is mounted.
Two files carry this information, (1) /etc/mtab and (2) /proc/mounts.
I use /proc/mounts to test for mounted filesystems.
I'd like you first to look at /proc/mounts; this command;
cat /proc/mounts
Suppose we want to know if /dev/hda1 or /dev/sda1 is mounted, we could use grep capabilities. Here's a fun little script.
Your arguments will be the device name or the mount point, and if you give bad arguments, you can get false positives. But we won't do that in our final script.
Code: Select all
#!/bin/bash
[ ! $1 ] && echo "no arguments, exiting" && exit
</proc/mounts grep $1 >/dev/null
[ x$? = x0 ] && echo $1 is mounted
Code: Select all
#!/bin/bash
[ ! $1 ] && echo "no arguments, exiting" && exit
</proc/mounts grep $1 >/dev/null
if [ x$? = x0 ] ; then
echo "$1 is mounted"
else
echo "$1 is not mounted"
fi
Code: Select all
[ ! $1 ] && echo "no arguments, exiting" && exit
for i in "$@" ; do
</proc/mounts grep $i >/dev/null
if [ x$? = x0 ] ; then
echo "$i is mounted"
else
echo "$i is not mounted"
fi
done
If you have grasped the file /proc/mounts, grep and its return code and how we will use it, you have grasped the meaning of this lesson.
Test and use the scripts as you please.
~
Chapter 59 - more building our Linux partition checking utility
Chapter 60 - various topics
A rant
I have about 30 books on C. Do we need that many? We shouldn't, but in a way maybe we do. I'll explain why, according to my opinion.
Often the author starts off with an easy teaching gradient, after reading a few chapters, the gradient becomes too steep. If it is genuinely too steep, we set the book down. Maybe pick up another. This cycle seems to repeat itself, starting easy, then getting too steep.
The saving grace is; after reading many beginning chapters, there is enough learning under our belts, the steeper chapters are not so steep. By rotating books, maybe we can make progress.
Why this series
Simply stated, it is a response to the wishes of a few people. Frankly, all the audience I need to motivate me is one person.
A lot to learn
If you have noticed, the chapters are not presented in an A-Z fashion. Even if one chapter is too hard, the next chapter may not even be related to the previous chapter. I hope there is no chance of the student running into the steep learning gradient I referred to in 'my rant'
A different approach
I've studied some excellent online lessons. I see no reason for me to reinvent the wheel or even compete. I'm in a position to give exercises very Puppy centric and other authors likely aren't in this position.
Who you are in relationship to your computer
In my opinion we wear (at least) three hats;
The value of scripting
Let's take Puppy as an example. Puppy is a carefully thought out hodgepodge, a literal hodgepodge of mostly open source applications.
Scripting is the 'glue' that puts the hodgepodge together and makes Puppy run.
Many of Puppy's homegrown applications are merely scripts hosting a graphical front-end and running back-end programs.
Making our scripts more attractive
I left you with 'cecho' to easily color your text output, which adds a nice finishing touch.
There are also programs we can use to enhance our programs, such as dialog. I leave this chapter with a picture of a project I'm working on for us. The code isn't ready to upload, but you can see by the picture how we can make professional, easy to use interfaces and menu items for our scripts.
~
Chapter 60 - various topics
A rant
I have about 30 books on C. Do we need that many? We shouldn't, but in a way maybe we do. I'll explain why, according to my opinion.
Often the author starts off with an easy teaching gradient, after reading a few chapters, the gradient becomes too steep. If it is genuinely too steep, we set the book down. Maybe pick up another. This cycle seems to repeat itself, starting easy, then getting too steep.
The saving grace is; after reading many beginning chapters, there is enough learning under our belts, the steeper chapters are not so steep. By rotating books, maybe we can make progress.
Why this series
Simply stated, it is a response to the wishes of a few people. Frankly, all the audience I need to motivate me is one person.
A lot to learn
If you have noticed, the chapters are not presented in an A-Z fashion. Even if one chapter is too hard, the next chapter may not even be related to the previous chapter. I hope there is no chance of the student running into the steep learning gradient I referred to in 'my rant'
A different approach
I've studied some excellent online lessons. I see no reason for me to reinvent the wheel or even compete. I'm in a position to give exercises very Puppy centric and other authors likely aren't in this position.
Who you are in relationship to your computer
In my opinion we wear (at least) three hats;
- 1) computer operator
2) system administrator
3) network administrator
The value of scripting
Let's take Puppy as an example. Puppy is a carefully thought out hodgepodge, a literal hodgepodge of mostly open source applications.
Scripting is the 'glue' that puts the hodgepodge together and makes Puppy run.
Many of Puppy's homegrown applications are merely scripts hosting a graphical front-end and running back-end programs.
Making our scripts more attractive
I left you with 'cecho' to easily color your text output, which adds a nice finishing touch.
There are also programs we can use to enhance our programs, such as dialog. I leave this chapter with a picture of a project I'm working on for us. The code isn't ready to upload, but you can see by the picture how we can make professional, easy to use interfaces and menu items for our scripts.
~
Chapter 60 - various topics
- Attachments
-
- init-editor.png
- (6.52 KiB) Downloaded 1710 times
Chapter 61 - setting date and time on the command line
setdate
settime
Scripts attached to post
~
Chapter 61 - setting date and time on the command line
setdate
Code: Select all
#!/bin/bash
[ ! $1 ] && echo "Usage example: setdate 20090721" && exit
date +%Y%m%d -s "$1" >/dev/null 2>&1
date
settime
Code: Select all
#!/bin/bash
if [ ! $1 ] ; then
echo "Usage examples:"
echo " settime 06:25:30PM"
echo " or"
echo " settime 18:25:30"
exit
fi
echo "$1" | grep M >/dev/null
if [ x$1 = x0 ] ; then
date +%T%p -s "$1" >/dev/null 2>&1
else
date +%T -s "$1" >/dev/null 2>&1
fi
date
~
Chapter 61 - setting date and time on the command line
- Attachments
-
- time-and-date.zip
- setdate + settime scripts
- (543 Bytes) Downloaded 1156 times
Chapter 62 - the init editor
The init editor code is ready. This utility should handle all the initrd.gz chores. It also makes backups.
The code is posted, but be sure and use the attached file, there are too many \s and maybe line wrapping for copy and paste.
This is also our first example of using ComeOn Dialog!, by Thomas E. Dickey
Script notes: I introduced an internal command 'exec'. In bash we can run other shells from our shell. In a practical sense, when we use exec, we stop the shell we are in and use a new shell, which is often a new script.
exec $0 means stop the script and run it again - in this case from the beginning. When using initedit, you will find it more convenient to have it open until your work is done, so that's why the exec $0. Remember $0 is the variable name for the program itself.
We also used cnt=`expr $cnt - 1`, unlike our other example this is arithmetic. It simply adds one to the value in cnt each time it runs, using the expr statement. You will use it and see it frequently.
As far as the dialog interface, I won't go into detail on this, we want an easy introduction and gradient which can hopefully come later.
~
Chapter 62 - the init editor
The init editor code is ready. This utility should handle all the initrd.gz chores. It also makes backups.
The code is posted, but be sure and use the attached file, there are too many \s and maybe line wrapping for copy and paste.
This is also our first example of using ComeOn Dialog!, by Thomas E. Dickey
Code: Select all
#!/bin/sh
main() {
check_for_file
options
process_answer
[ -f /tmp/initedit.tmp ] && rm /tmp/initedit.tmp
}
check_for_file() {
if [ ! -f initrd.gz ] ; then
dialog --backtitle 'File not found!' --msgbox "The required file: \
initrd.gz does not exist in this directory \
please change to the directory which has initrd.gz" 7 55
clear
exit
fi
}
options() {
dialog --backtitle "Init Editor Main Menu - Puppy Versions 3.xx and 4.xx" \
--nocancel --menu "Please choose" 0 35 8 \
"x" "eXit" \
"1" "Extract initrd.gz" \
"2" "Delete extracted tree" \
"3" "Compress initrd.gz" \
"4" "Edit init - geany" \
"5" "Edit init - medit" \
"6" "Edit init - mp" \
"7" "Midnight Commander" \
2>/tmp/initedit.tmp
}
make_initdir() {
cd initdir
zcat ../initrd.gz | cpio -i -d
cd ..
}
process_answer() {
answer=`cat /tmp/initedit.tmp`
case $answer in
1)
[ ! -d initdir ] && make_initdir
;;
2)
[ -d initdir ] && rm -rf initdr
;;
3)
cnt=2
if [ -d initdir ] ; then
cp initrd.gz initrd1.gz
for i in 1 2 3 4 5 ; do
cp initrd${i}.gz initrd${cnt}.gz >/dev/null 2>&1
cnt=`expr $cnt - 1`
done
fi
cd initdir
find . | cpio -o -H newc | gzip -9 > ../initrd.gz
cd ..
;;
4)
[ ! -d initdir ] && make_initdir
geany initdir/init &
;;
5)
[ ! -d initdir ] && make_initdir
medit initdir/init &
;;
6)
[ ! -d initdir ] && make_initdir
mp initdir/init
;;
7)
mc initdir .
;;
*)
[ -f /tmp/initedit.tmp ] && rm /tmp/initedit.tmp
clear ; exit
;;
esac
exec $0
}
main
exec $0 means stop the script and run it again - in this case from the beginning. When using initedit, you will find it more convenient to have it open until your work is done, so that's why the exec $0. Remember $0 is the variable name for the program itself.
We also used cnt=`expr $cnt - 1`, unlike our other example this is arithmetic. It simply adds one to the value in cnt each time it runs, using the expr statement. You will use it and see it frequently.
As far as the dialog interface, I won't go into detail on this, we want an easy introduction and gradient which can hopefully come later.
~
Chapter 62 - the init editor
- Attachments
-
- initedit.zip
- init editor script
- (895 Bytes) Downloaded 1174 times
Chapter 63 - auto ext2|3 filesystem check and repair
The scripts in this post will automatically find, check and repair as needed your unmounted ext2 and ext3 partitions.
Script: autofsck
Script: autofsck4rclocal
What you do with these scripts is up to you. In previous chapters, I explained portions of the programming logic which constitutes the scripts.
Some people think it takes too long to check the file systems each boot. Some people think it is unnecessary. Some people never check anything at all.
With ext3 partitions it takes me about 1/2 second to do the filesystem check. Your ext2 and ext3 partitions keep count of days between full checks and number of mounts between full checks.
A full check is typically about every 26 mounts, the full check is time consuming, no doubt.
(If you are like me, you are the system administrator - that's how it is)
Between these two scripts, depending on which script you use, you have the ability to run them as you please, or each boot, or never at all.
If nothing else, please read the two scripts, they are almost identical, except in style. See what style you like the best, try and understand each line.
~
Chapter 63 - auto ext2|3 filesystem check and repair
The scripts in this post will automatically find, check and repair as needed your unmounted ext2 and ext3 partitions.
Script: autofsck
Code: Select all
#!/bin/bash
main()
{
variables
partition_types
}
variables()
{
partitions=`fdisk -l | grep "83 Linux" | cut -d " " -f 1 | tr "\n" " "`
}
partition_types()
{
for i in $partitions ; do
guess_fstype $i | grep ext[23]>/dev/null
if [ x$? = x0 ] ; then
</proc/mounts grep $i>/dev/null
if [ x$? != x0 ] ; then
echo -en "\\033[1;36m""Checking $i"
echo -e "\\033[1;36m"
e2fsck -y $i
fi
fi
done
}
main
Code: Select all
## BEGIN AUTO EXT2|3 FSCK
partitions=`fdisk -l | grep "83 Linux" \
| cut -d " " -f 1 | tr "\n" " "`
for i in $partitions ; do
guess_fstype $i | grep ext[23]>/dev/null
if [ x$? = x0 ] ; then
</proc/mounts grep $i>/dev/null
if [ x$? != x0 ] ; then
echo -en "\\033[1;36m""Checking $i">/dev/console
echo -e "\\033[1;36m">/dev/console
e2fsck -y $i >/dev/console
fi
fi
done
## END AUTO EXT2|3 FSCK
- 1) find 83 Linux partitions
2) filter out the ext2 and ext3
3) see if they are unmounted
4) if so do a file system check
5) provide on screen feedback
Some people think it takes too long to check the file systems each boot. Some people think it is unnecessary. Some people never check anything at all.
With ext3 partitions it takes me about 1/2 second to do the filesystem check. Your ext2 and ext3 partitions keep count of days between full checks and number of mounts between full checks.
A full check is typically about every 26 mounts, the full check is time consuming, no doubt.
(If you are like me, you are the system administrator - that's how it is)
Between these two scripts, depending on which script you use, you have the ability to run them as you please, or each boot, or never at all.
If nothing else, please read the two scripts, they are almost identical, except in style. See what style you like the best, try and understand each line.
~
Chapter 63 - auto ext2|3 filesystem check and repair
- Attachments
-
- autofsck.zip
- (825 Bytes) Downloaded 1150 times
Chapter 64 - the important filesystem checks
The pup_save file. That's where your operating system is, (for frugal users). It's the file you really want to keep free of errors. It's also the file most susceptible to errors.
A primary obstacle is; we can only safely check and repair filesystems when they are not mounted. The pup_save file gets mounted early in the boot process.
Moreover, over the last several releases, Barry has implemented various techniques for dealing with this. Considering the changes, I can't come up with a one solution.
Version 4.00 did the e2fsck automatically, people complained it was taking too long.
On newer versions, I've noted a variable which can be set puppy pfix=fsck
From the way I read the forum, most people are probably using a version with this variable. From that standpoint, maybe there isn't even a problem to solve.
I have no desire or intention of running Puppy or any Linux on filesystems with errors, so, if I were the admin over Puppy computers, I'd put the pfix=fsck line in GRUB.
The other partition of importance is the pup_save host partition. I modified my init to remove all checking of the pup_save file and set it to check the host and the pup_save file before anything of consequence occurs. Code excerpt to follow:
The host gets checked, the pup_save gets checked and note: it isn't even an ext2 format.
I won't explain anything concerning the above code, because of so many modifications elsewhere, and how they all fit together.
Point here is if an open source system isn't doing as you want it to, there is usually something, often a lot you can do to it.
You get the idea - man over machine - and it's a lot of fun.
~
Chapter 64 - the important filesystem checks
The pup_save file. That's where your operating system is, (for frugal users). It's the file you really want to keep free of errors. It's also the file most susceptible to errors.
A primary obstacle is; we can only safely check and repair filesystems when they are not mounted. The pup_save file gets mounted early in the boot process.
Moreover, over the last several releases, Barry has implemented various techniques for dealing with this. Considering the changes, I can't come up with a one solution.
Version 4.00 did the e2fsck automatically, people complained it was taking too long.
On newer versions, I've noted a variable which can be set puppy pfix=fsck
From the way I read the forum, most people are probably using a version with this variable. From that standpoint, maybe there isn't even a problem to solve.
I have no desire or intention of running Puppy or any Linux on filesystems with errors, so, if I were the admin over Puppy computers, I'd put the pfix=fsck line in GRUB.
The other partition of importance is the pup_save host partition. I modified my init to remove all checking of the pup_save file and set it to check the host and the pup_save file before anything of consequence occurs. Code excerpt to follow:
Code: Select all
mount -t proc none /proc
mount -t sysfs none /sys
mount -t rootfs -o remount,rw rootfs /
ln -s /proc/mounts /etc/mtab #resize2fs,e2fsck need this.
fsck_func() {
echo -en "\\033[1;35m" >/dev/console #35=purple
echo "filesystem check host please wait"
/bin/e2fsck -y /dev/$PDEV1 >/dev/console
/bin/mount -t ext3 /dev/$PDEV1 /mnt/data
echo -en "\\033[1;35m" >/dev/console #35=purple
echo "filesystem check pup_save.3fs"
/bin/e2fsck -y /mnt/data/$PSUBDIR/pup_save.3fs >/dev/console
/bin/umount /mnt/data
}
fsck_func
I won't explain anything concerning the above code, because of so many modifications elsewhere, and how they all fit together.
Point here is if an open source system isn't doing as you want it to, there is usually something, often a lot you can do to it.
You get the idea - man over machine - and it's a lot of fun.
~
Chapter 64 - the important filesystem checks
Chapter 65 - assuring only one instance is running
I prepare these posts with Puppy's excellent outliner 'notecase'. Notecase allows multiple instances of itself. It also allows multiple instances of the same file.
To make things easy, I have a shell script called tui to open notecase with tui.ncd also loaded. Problem is notecase can open more than one tui.ncd and I can damage a document by editing a document open elsewhere.
I wish to demonstrate in this chapter how we can be assured we only have one instance of file open, using conditional checking and branching.
Remember how we can uses grep's exit code to verify conditions? We'll do it again here.
Was that easy?
Notes:
/dev/null is a mysterious black hole where things disappear forever and ever. You've see me use it before, now you know why, I don't want to see the output.
grep -v grep is saying: do not show any lines containing grep. problem is ps shows all processes, when we ran 'grep tui.ncd', which is a match, it became a process and we need filter it out with the -v switch. now we won't have a false positive.
The last argument in our pipe chain is the exit code which will be used. If 0, then tui.ncd is already running, (a true condition) we print a message and the shell having nothing else to do exits at the end.
else is a false condition, but that's not why it executes commands. It runs commands because nothing else did, (if that were the case).
If else runs, we start notecase tui.ncd with the & key to put it in the background so we can have our prompt back.
Assignment - Nothing to do with this code except understand it - if you want, modify it and come up with something useful for you.
~
Chapter 65 - assuring only one instance is running
I prepare these posts with Puppy's excellent outliner 'notecase'. Notecase allows multiple instances of itself. It also allows multiple instances of the same file.
To make things easy, I have a shell script called tui to open notecase with tui.ncd also loaded. Problem is notecase can open more than one tui.ncd and I can damage a document by editing a document open elsewhere.
I wish to demonstrate in this chapter how we can be assured we only have one instance of file open, using conditional checking and branching.
Remember how we can uses grep's exit code to verify conditions? We'll do it again here.
Code: Select all
#!/bin/bash
ps | grep -v grep | grep tui.ncd >/dev/null
if [ x$? = x0 ] ; then
echo " notecase tui.ncd is already running, exiting . . ."
else
notecase /root/Desktop/tui.ncd &
fi
Notes:
/dev/null is a mysterious black hole where things disappear forever and ever. You've see me use it before, now you know why, I don't want to see the output.
grep -v grep is saying: do not show any lines containing grep. problem is ps shows all processes, when we ran 'grep tui.ncd', which is a match, it became a process and we need filter it out with the -v switch. now we won't have a false positive.
The last argument in our pipe chain is the exit code which will be used. If 0, then tui.ncd is already running, (a true condition) we print a message and the shell having nothing else to do exits at the end.
else is a false condition, but that's not why it executes commands. It runs commands because nothing else did, (if that were the case).
If else runs, we start notecase tui.ncd with the & key to put it in the background so we can have our prompt back.
Assignment - Nothing to do with this code except understand it - if you want, modify it and come up with something useful for you.
~
Chapter 65 - assuring only one instance is running
Last edited by Bruce B on Fri 24 Jul 2009, 07:07, edited 1 time in total.
Chapter 66 acd (means auto change directories)
The code in this chapter is unique, you might have to pay very careful attention.
First
I want you to be able to easily open .bashrc, edit it and source it. Here is the command I want you to copy and paste:
alias ea='mp /root/.bashrc ; source /root/.bashrc'
Notes: if you don't like mp, use another editor. Also, when using spaces in your .bashrc file always use ' after the = and ' at the end of line.
ea means 'edit alias'
Second
Copy and paste this command to .bashrc;
alias rf='source /root/.bashrc'
This will easily re-source an existing instance of bash. Suppose you have five instances open and change one. The other four need sourced again.
Third
Remember, we can change directories with aliases. I can type usrbin faster and easier than I can type cd /usr/bin.
I now give you a script which will add change directory aliases from the command line, without the need to open .bashrc and edit it. I call the script acd for auto change directories
To use, simply type acd + the name of the shortcut you want- when you are in the directory you want to add a shortcut to.
Example: when in /root/.mozilla, you can type acd .mozilla and your shortcut is added. You no longer need to type cd /root/.mozilla. Just type .mozilla Then use 'rf' to activate it in the current shell. Otherwise, it will activate next time you open it.
Forth
Using colors: I gave you colors to work with, this is the first script where I added colors. If you didn't install colors, then you must change the cecho to echo. If the colors are not to your liking you need to modify them
Lastly, here is the script;
Assignment - this file very useful, but optional. Please use attached file rather than the pasted code. Enjoy
~
Chapter 66 acd (means auto change directories)
The code in this chapter is unique, you might have to pay very careful attention.
First
I want you to be able to easily open .bashrc, edit it and source it. Here is the command I want you to copy and paste:
alias ea='mp /root/.bashrc ; source /root/.bashrc'
Notes: if you don't like mp, use another editor. Also, when using spaces in your .bashrc file always use ' after the = and ' at the end of line.
ea means 'edit alias'
Second
Copy and paste this command to .bashrc;
alias rf='source /root/.bashrc'
This will easily re-source an existing instance of bash. Suppose you have five instances open and change one. The other four need sourced again.
Third
Remember, we can change directories with aliases. I can type usrbin faster and easier than I can type cd /usr/bin.
I now give you a script which will add change directory aliases from the command line, without the need to open .bashrc and edit it. I call the script acd for auto change directories
To use, simply type acd + the name of the shortcut you want- when you are in the directory you want to add a shortcut to.
Example: when in /root/.mozilla, you can type acd .mozilla and your shortcut is added. You no longer need to type cd /root/.mozilla. Just type .mozilla Then use 'rf' to activate it in the current shell. Otherwise, it will activate next time you open it.
Forth
Using colors: I gave you colors to work with, this is the first script where I added colors. If you didn't install colors, then you must change the cecho to echo. If the colors are not to your liking you need to modify them
Lastly, here is the script;
Code: Select all
#!/bin/bash
main() {
variables $1
check_dupes $1
make_alias $1
}
variables() {
$clr
file=/root/.bashrc
[ ! $1 ] && cecho red " missing argument" && exit
name=$1
dir=`pwd`
tmpfile=/dev/shm/bashrc
}
check_dupes() {
cecho white
< $file grep "alias $1="
if [ "$?" = "0" ] ; then
cecho yellow "alias name \"$1\" already exists"
cecho white "replace it (y,n)"
color black
read -n 1 a
if [ "$a" = "y" ] ; then
color white
< $file grep -v $name>$tmpfile
cp $tmpfile $file
return
else
echo
fi
exit
fi
}
make_alias() {
cecho white "alias $1='cd $dir'" n
cecho white " "
cecho green "added to list"
echo "alias $1='cd $dir'" >> $file
}
main $1
~
Chapter 66 acd (means auto change directories)
- Attachments
-
- acd.zip
- (531 Bytes) Downloaded 1140 times
Chapter 67 - easy note taking
As a part of our computing tasks, we often want to jot down a few notes. With the GUI, this might involve opening a text editor, making our notes, saving changes and closing.
This task can be made much easier with a simple script, considering command line users often have the emulator open at all times.
For purpose of this chapter we will call our script note.
That's an easy enough script. When done jotting the notes, hit ctrl+d to close note and save your changes.
Like many, if not most scripts, they can be enhanced with features added, we'll do it.
Some scripts we plan to distribute, they need to have maximum portability. As a rule, we want all our scripts to be as portable as is reasonably possible. But for ourselves we might do non conventional things to make them easier.
In this case, if I type note and any character it brings up a menu. For example:
Comments
As per style all control is in main.
We've seen examples of nesting loop and if statements. Here we see an example of nesting a function.
Reinforcement: Bash reads from top to bottom. We must read the function before calling it. This is why main is at the bottom and in the case of the nested function, it is read before called.
Sometimes we want to take notes without giving someone an opportunity to read over our shoulder. I included functionality to lower contrast. My background is black so I used black. If you want to use this script, you may need to modify these colors according to your background.
If you didn't install cecho, well, modify the script accordingly.
Typically our terminal is black with a light gray text. With Puppy it might be a white bg with a black fg.
I like colors for their own sake. Also, I think colors can give a nice finished look to our scripts.
In this script I've used 'dialog' for some of the options. But, I haven't taught dialog yet. I would like to emphasize dialog is not a graphics program. Everything you are looking at in dialog is text.
See how you like the command line note utility, what you can learn or do with it.
~
Chapter 67 - easy note taking
(don't copy and paste, use the attachment)
As a part of our computing tasks, we often want to jot down a few notes. With the GUI, this might involve opening a text editor, making our notes, saving changes and closing.
This task can be made much easier with a simple script, considering command line users often have the emulator open at all times.
For purpose of this chapter we will call our script note.
Code: Select all
#!/bin/bash
cat >> /root/my-documents/note.txt
Like many, if not most scripts, they can be enhanced with features added, we'll do it.
Some scripts we plan to distribute, they need to have maximum portability. As a rule, we want all our scripts to be as portable as is reasonably possible. But for ourselves we might do non conventional things to make them easier.
In this case, if I type note and any character it brings up a menu. For example:
- note a
note -
note note
note (with no argument works normally)
Code: Select all
#!/bin/bash
main() {
variables
[ "$1" != "" ] && give_menu
case_answer
}
variables() {
$clr
fn="/root/my-documents/note.txt"
answer="/tmp/noteoptions.tmp"
[ -f $answer ] && rm $answer
}
case_answer() {
take_notes() {
cecho black "Ctrl + D to finish"
cecho green
cat >> $fn
clear
exit
}
[ ! -f $answer ] && take_notes
ans=`cat $answer`
case $ans in
x) clear ; exit ;;
c) clear ; cecho black ; cat >> $fn ; clear ;;
d) dialog --title "$fn" --textbox $fn 22 70 ; clear ;;
e) mp $fn ; clear ;;
s) ispell $fn ; clear ;;
*) clear ; exit ;;
esac
[ -f $answer ] && rm $answer
}
give_menu() {
dialog --backtitle "Note Menu" \
--nocancel --menu "Options for note.txt" 0 30 5 \
"x" "exit" \
"c" "cli low contrast" \
"d" "display file" \
"e" "edit in mp" \
"s" "spell check" \
2>/tmp/noteoptions.tmp
}
main $1
As per style all control is in main.
We've seen examples of nesting loop and if statements. Here we see an example of nesting a function.
Reinforcement: Bash reads from top to bottom. We must read the function before calling it. This is why main is at the bottom and in the case of the nested function, it is read before called.
Sometimes we want to take notes without giving someone an opportunity to read over our shoulder. I included functionality to lower contrast. My background is black so I used black. If you want to use this script, you may need to modify these colors according to your background.
If you didn't install cecho, well, modify the script accordingly.
Typically our terminal is black with a light gray text. With Puppy it might be a white bg with a black fg.
I like colors for their own sake. Also, I think colors can give a nice finished look to our scripts.
In this script I've used 'dialog' for some of the options. But, I haven't taught dialog yet. I would like to emphasize dialog is not a graphics program. Everything you are looking at in dialog is text.
See how you like the command line note utility, what you can learn or do with it.
~
Chapter 67 - easy note taking
(don't copy and paste, use the attachment)
- Attachments
-
- note.zip
- (582 Bytes) Downloaded 1100 times